Spring Boot入門
プロジェクトの構成
このレッスンでは、Spring Boot のプロジェクトを開いたときに目に入るディレクトリとファイルが、それぞれ何のためにあるのかを読み解けるようになります。
プロジェクトは Spring Initializr で作ります
Spring Boot のプロジェクトを一から手で組み立てる人はほとんどいません。Spring Initializr という公式のジェネレータを使います。ブラウザなら https://start.spring.io を開き、IntelliJ IDEA なら新規プロジェクト作成画面から同じものが呼び出せます。
そこで選ぶ項目は次の通りです。
| 項目 | 意味 | よくある選択 |
|---|---|---|
| Project | ビルドツール | Gradle または Maven |
| Language | 言語 | Java |
| Spring Boot | バージョン | 安定版の最新 (3.x) |
| Group | 組織を表す識別子 | com.example |
| Artifact | 成果物の名前 | demo |
| Packaging | 配布形式 | Jar |
| Java | JDK のバージョン | 17 または 21 |
| Dependencies | 使う機能 | Spring Web、Spring Data JPA など |
Dependencies で選んだものが、そのまま スターター依存 としてビルドファイルに書き込まれます。ここで Spring Web を選ぶかどうかで、生成されるプロジェクトが Web サーバーとして起動するかどうかが変わります。何も選ばずに作ると、起動してすぐ終了するだけのアプリになります。
できあがるディレクトリの形
生成されたプロジェクトは、Maven や Gradle の標準レイアウトに従います。
プレーンテキスト
demo
├── build.gradle (Gradle の場合)
├── settings.gradle
├── gradlew
└── src
├── main
│ ├── java
│ │ └── com/example/demo
│ │ └── DemoApplication.java
│ └── resources
│ ├── application.properties
│ ├── static
│ └── templates
└── test
└── java
└── com/example/demo
└── DemoApplicationTests.java覚えることは 2 つだけです。src/main/java にはコンパイルされる Java ファイルを置く、src/main/resources にはコンパイルされない資材を置く です。設定ファイル、SQL のスクリプト、画像、HTML テンプレートはすべて後者に入ります。ビルドすると両方が同じ jar の中に詰め込まれ、src/main/resources の中身はクラスパス直下から読める状態になります。
src/test 以下も同じ構造で、こちらはテストの実行時にだけ使われ、本番の jar には含まれません。src/test/resources に別の application.properties を置けば、テストのときだけ設定を差し替えられます。
gradlew は Gradle ラッパーと呼ばれるスクリプトで、Gradle 本体が手元に入っていなくても、必要なバージョンを自動で取ってきて実行してくれます。だからチーム全員が同じバージョンでビルドできます。Maven なら mvnw が同じ役割です。
ビルドファイルには依存とビルド手順を書きます
Gradle なら build.gradle、Maven なら pom.xml です。どちらも書く内容は同じで、どのライブラリを使うか、どの Java バージョンでコンパイルするか、どうやって jar を作るかを宣言します。
groovy
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}注目してほしいのは、スターター依存の行に バージョン番号が書かれていない ことです。io.spring.dependency-management プラグインが、Spring Boot のバージョンに合う組み合わせを一括で決めてくれます。ライブラリの相性を自分で調べなくてよいのが、Spring Boot の大きな価値の 1 つです。
implementation は本番でもテストでも使う依存、testImplementation はテストのときだけ使う依存、runtimeOnly はコンパイル時には要らないが実行時に必要な依存を表します。データベースのドライバは典型的な runtimeOnly です。
設定は application.properties に集めます
src/main/resources/application.properties は、アプリ全体の設定を書く場所です。
Properties
server.port=8081
spring.datasource.url=jdbc:h2:mem:testdb
spring.jpa.hibernate.ddl-auto=update
logging.level.org.springframework.web=DEBUGapplication.yml という YAML 形式でも書けて、どちらを選んでも意味は同じです。階層が深い設定を書くときは YAML のほうが読みやすくなります。
ここに書いた値は、自分のコードからも @Value("${server.port}") や @ConfigurationProperties で読み出せます。パスワードのような秘密は、ファイルに直接書かず環境変数から渡すのが基本です。spring.datasource.password=${DB_PASSWORD} と書けば、実行時の環境変数が入ります。
環境ごとに設定を変えたいときは application-dev.properties や application-prod.properties を用意し、起動時にプロファイルを指定します。これを プロファイル と呼びます。
パッケージ構成には強い慣習があります
src/main/java の下は、com.example.demo のようにドメイン名を逆にした形で始めます。そして メインクラスは必ず一番上のパッケージに置きます。
理由は、次のレッスンで扱うコンポーネントスキャンにあります。@SpringBootApplication の付いたクラスは、自分のパッケージとその配下だけを走査対象にします。メインクラスを深い場所に置くと、その外側にあるコントローラやサービスが見つからず、動かない原因の分かりにくいバグになります。
配下の分け方には大きく 2 つの流派があります。
プレーンテキスト
com.example.demo com.example.demo
├── DemoApplication.java ├── DemoApplication.java
├── controller ├── user
│ └── UserController.java │ ├── UserController.java
├── service │ ├── UserService.java
│ └── UserService.java │ └── UserRepository.java
├── repository └── order
│ └── UserRepository.java ├── OrderController.java
└── domain └── OrderService.java
└── User.java左が レイヤごと に分ける形で、入門段階ではこちらが分かりやすく、教材でもよく使われます。右が 機能ごと に分ける形で、規模が大きくなるとこちらのほうが変更範囲がまとまります。どちらが正解ということはなく、チームで統一されていることのほうが大事です。このコースでは左の形を前提に説明していきます。
起動の入口はメインクラスです
Java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}普通の Java プログラムと同じく main から始まります。SpringApplication.run が、アプリケーションコンテキストを組み立て、コンポーネントをスキャンし、自動設定を適用し、組み込み Tomcat を起動するところまでを一気にやります。この 1 行の中で何が起きているのかは、次のレッスンで確認します。