12月2日、リンクステーションホール青森で行われたMr.Childrenのライブ最高でした。
久しぶりの投稿になります、mukaiyachiです。
近年Springを扱う案件にいくつか参加しました。
ただ社内でSpringを使ったことがある人は限られているため、少しでも増えるといいなーという思いで、先日社内の勉強会でSpringについて少し紹介しました。
今回の記事はその内容をブログ用に一部を変更したものになります。
社内の勉強会と同様に、こちらをきっかけに少しでもSpringに使ったことある人が増えたら幸いです。
記載するものはSpringが持つ機能の一部で、まだまだ他にも沢山あるので興味が湧いた方は調べたり使ってみたりしてみてください!
Springとは
- JavaのFrameworkです。(KotlinやGroovyなど他のJVM言語でも使用可)
- 1つのプロジェクトではなく、Spring Frameworkを中心とした複数のプロジェクトの総称になります。
- 全てを使用する必要はなく、必要なものを取り入れて開発を行っていきます。
Springのプロジェクト例
- Spring Framework
- アプリケーション全体にわたって便利な機能を提供します。
(DIコンテナ、Spring MVC、Sprring JDBC、宣言的トランザクション、テストサポート)
- Spring Security
- 認証と認可を主としたセキュリティまわりの機能を提供します。
- Spring Boot
- Springを使用した開発の生産性やメンテナンス性を向上させるライブラリ&ツールです。
(ライブラリ一括取得、オートコンフィグレーション、組み込みAPサーバー)
- Spring Batch
- Springの機能を使ったバッチ処理機能を提供します。
プロジェクトの作成
- プロジェクトの作成方法は、EclipseやIntelliJ IDEAにプラグインを入れて作成など様々ありますが、特徴的なのはSpring Initializrによる作成です。
- Spring InitializrはSpringのプロジェクト作成用のサイトで、プロジェクトの雛形を作成することができます。
- サイト上でビルドツール、プログラム言語、プロジェクト名、使用するライブラリなどを選択・入力してプロジェクトを作成します。
- プロジェクトはZipでダウンロードでき、各IDEでインポートすれば使用できます。
組み込みAPサーバ
- Spring BootにはTomcatが組み込みAPサーバとして付属しています。
- 組み込みAPサーバを使用すれば、サーバマシンに事前にAPサーバをインストールする必要がありません。
- アプリケーションはサーバマシンにjarファイルを直接デプロイするだけになります。
(もし複数アプリケーション実行する際は、設定ファイルでポートの調整など必要になります。)
- Spring Bootは組み込みAPサーバの起動を自動的に行なってくれます。
- APサーバ導入済みの環境向けにwar形式のパッケージを作成して起動させることも出来ます。
- 設定もアプリケーション用とAPサーバ用で一元的に行うことが出来るので、メンテナンス性が良くなるという面もあります。
アノテーション
- クラスやメソッドなどに付加情報を設定するためのJavaの仕組みです。
- @xxxxxの形で記述する。(xxxxxにはアノテーション名が入ります。)
- Spring特有のものではなく以前よりJavaにある機能ですが、近年ではより良く使われるようになっているようで、これを使いこなすのがSpringの肝と言えるかもしれません。
- Springオリジナルのアノテーションも存在します。
- それらに加えてJava標準のアノテーション、ライブラリが提供するアノテーションなど様々組み合わせ使われます。
- 自分でオリジナルのアノテーション作成も可能です。
ここからはいくつかアノテーションを紹介していきます。
コンストラクタ関係
ここで紹介するのはLomnokというライブラリのアノテーションです。
Lombokは、最近のJavaのプロジェクトでは必ずといって良いほど使用されるライブラリです。
@NoArgsConstructor
- デフォルトコンストラクタを自動生成します。
- 適用前
1 2 3 4 5 6 7 8 |
public class User1 { private long id; private String name; private int age; public User1() { } } |
- 適用後
1 2 3 4 5 6 7 8 |
import lombok.NoArgsConstructor; @NoArgsConstructor public class User1 { private long id; private String name; private int age; } |
@RequiredArgsConstructor
- finalフィールドを引数で初期化するコンストラクタを自動生成します。
- 適用前
1 2 3 4 5 6 7 8 9 10 11 |
public class User2 { private long id; private String name; private int age; public User2(long id, String name, int age) { this.id = id; this.name = name; this.age = age; } } |
- 適用後
1 2 3 4 5 6 |
@AllArgsConstructor public class User2 { private long id; private String name; private int age; } |
@AllArgsConstructor
- 全フィールドを引数で初期化するコンストラクタを自動生成します。
- 適用前
1 2 3 4 5 6 7 8 9 |
public class User3 { private final long id; private String name; private int age; public User3(long id) { this.id = id; } } |
- 適用後
1 2 3 4 5 6 |
@RequiredArgsConstructor public class User3 { private final long id; private String name; private int age; } |
getter、setter、toString、equals、hashCodeを自動生成
こちらもLombokのアノテーションです。
@Data
- 下記のアノテーションを全て付与したのと同じ状態になります。
- @Getter
- getterメソッドを自動生成します。
- @Setter
- setterメソッドを自動生成します。
- @ToString
- 全フィールドを1つの文字列表現に変換するtoStringメソッドを自動生成します。
- @EqualsAndHashCode
- 全フィールドを使用してequalsメソッドとhashCodeメソッドを自動生成します。
- @RequiredArgsConstructor
- finalフィールドを引数で初期化するコンストラクタを自動生成します。
- @Getter
- 適用前
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
public class Staff { private final long id; private String department; public Staff(long id) { this.id = id; } public long getId() { return this.id; } public String getDepartment() { return this.department; } public void setDepartment(String department) { this.department = department; } public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof Staff)) return false; final Staff other = (Staff) o; if (!other.canEqual((Object) this)) return false; if (this.getId() != other.getId()) return false; final Object this$department = this.getDepartment(); final Object other$department = other.getDepartment(); if (this$department == null ? other$department != null : !this$department.equals(other$department)) return false; return true; } protected boolean canEqual(final Object other) { return other instanceof Staff; } public int hashCode() { final int PRIME = 59; int result = 1; final long $id = this.getId(); result = result * PRIME + (int) ($id >>> 32 ^ $id); final Object $department = this.getDepartment(); result = result * PRIME + ($department == null ? 43 : $department.hashCode()); return result; } public String toString() { return "Staff(id=" + this.getId() + ", department=" + this.getDepartment() + ")"; } } |
- 適用後
1 2 3 4 5 |
@Data public class Staff { private final long id; private String department; } |
- 使用例
- Staffクラス自体には記述されていませんが、コンストラクタやsetterメソッドが使用できることが確認できるかと思います。
1 2 3 4 |
public void register() { Staff staff = new Staff(1); staff.setDepartment("販売部門"); } |
宣言的トランザクション
こちらはSpringのアノテーションです。
@Transactional
- クラスやメソッドに付けると、その中で実行される処理はデータベースのトランザクション制御(開始、コミット、ロールバック)が自動的に行われます。
- メソッドに付与 (registerメソッドのみトランザクション制御対象)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@Service public class BookingService { private final BookingRepository bookingRepository; public BookingService(BookingRepository bookingRepository) { this.bookingRepository = bookingRepository; } public void getBooking() { bookingRepository.findAll(); } @Transactional public void register() { bookingRepository.register(); } public void delete() { bookingRepository.delete(); } } |
- クラスに付与 (クラス内のメソッド全てトランザクション制御対象)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@Service @Transactional public class BookingService { private final BookingRepository bookingRepository; public BookingService(BookingRepository bookingRepository) { this.bookingRepository = bookingRepository; } public void getBooking() { bookingRepository.findAll(); } public void register() { bookingRepository.register(); } public void delete() { bookingRepository.delete(); } } |
非同期処理
こちらもSpringのアノテーションです。
@EnableAsyncと@Asyncを使用して実現します。
@EnableAsync
- Springを起動するクラスに付与します。
- Springアプリケーションで非同期処理実行を有効にします。
1 2 3 4 5 6 7 |
@SpringBootApplication @EnableAsync public class SpringDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringDemoApplication.class, args); } } |
@Async
- 付与したメソッドの処理は別スレッドで非同期実行されます。
1 2 3 4 5 6 7 |
@Service public class BookingService { @Async public void sendEmail() { // 時間のかかる処理(メール送信など) } } |
ルーティング
こちらはSpringのアノテーションです。
- @RequestMappingをControllerクラスやそのメソッドに付与して設定します。
- 引数にメソッドに紐づけたいリクエストのパスを設定します。
- 引数ではその他にHTTPメソッドも設定できます。
- 下記のアノテーションは@RequestMappingの各HTTPメソッド専用バージョンです。
- メソッドにのみ付与できます。
- 引数でHTTPメソッドは設定不可です。
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
メソッドにのみ付与した場合
1 2 3 4 5 6 7 8 9 10 |
@RestController public class BookingController { @GetMapping("/xyz") public void getBooking() { } @PostMapping("/xyz") public void register() { } } |
例えばローカル環境で、http://localhost:8080/xyzの様なURLにアクセスすると、BookingControllerのgetBookingメソッドが実行されます。
クラスとメソッドに付与した場合
1 2 3 4 5 6 7 8 9 10 11 |
@RestController @RequestMapping("/abc") public class BookingController { @GetMapping("/xyz") public void getBooking() { } @PostMapping("/xyz") public void register() { } } |
・例えばローカル環境で、http://localhost:8080/abc/xyzの様なURLにアクセスすると、BookingControllerのgetBookingメソッドが実行されます。
・クラスには付与せずgetBookingメソッドにのみ @GetMapping(“/abc/xyz”)と設定した場合も同じになります。
今回の記事は以上となります。
今回も読んでいただきありがとうございました!
最後になりますが、早いもので今年も年末となりました。
今年もこのブログを見に来ていただいてありがとうございました。
以前に比べてなかなか投稿がされなくなってしまいましたが、ちょっと少なすぎたので2024年はもう少し投稿できればと思います。
それでは少し早いかもしれませんが、皆様良いお年をお迎えください!