はじめに:Spring Bootを用いて「最短距離」でWebアプリを作るため
はじめまして、学生エンジニアの@huyunokiです。
【お願い】 本記事はインターン経験のある学生が学習過程を記録したものです。内容に誤りや非効率な点が含まれている可能性がありますので、ぜひご指摘いただけますと幸いです。
Spring Bootは多機能で複雑そうに見えますが、「Webアプリを動かすために最低限必要な機能」に絞って学べば、驚くほど短い期間でバックエンドを作れるようになります。
この記事は、初めてSpring Bootで開発を行った僕が実際に一つのWebアプリを開発する過程で「これだけは絶対に必要だった」という知識と設定を厳選し、「初めてSpring Bootを学ぶ人が、この手順だけ見たら裏側を完成できる」ことを目的としています。
ターゲット読者
- Javaの基本(データ型、ループなど)は理解している人
- 初めてSpring BootでWebアプリのバックエンドを作りたい人
- Web開発の全体像を掴みたい人
Part 1: アプリケーションの土台(設定とWebの基本)
まずは、アプリが動くための基本的な設定と、Webの通信ルールを定義します。
1-1. 必須の基本設定(application.properties)
src/main/resources/application.propertiesに以下を設定することで、アプリの動作環境を定義します。
| 内容 | コード | 役割 |
|---|---|---|
| ポート番号設定 | server.port=7777 |
Webアプリが起動するポート番号を指定(デフォルトは8080)。 |
| コンテキストパス設定 | server.servlet.context-path=/shop |
アプリのルートパスを定義(例:http://localhost:7777/shop/となる)。 |
| Thymeleafキャッシュ無効化 | spring.thymeleaf.cache=false |
開発中にHTMLを変更した際、すぐに反映されるようにする(開発時必須)。 |
| Thymeleaf名前空間 | <html xmlns:th="http://www.thymeleaf.org/"> |
HTMLファイルの<html>タグに追加し、Thymeleafの属性を使えるようにする。 |
1-2. Web通信の基本:GETとPOSTの使い分け
使うHTTPリクエストは最低限で2種類あり、Controller側で使い分けます。
| 種類 | 特徴 | 使い分け |
|---|---|---|
GET |
パラメーターがURLに直接表示される。 | データの参照(一覧表示、詳細表示、リンクのクリックなど)。 |
POST |
パラメーターが内部的に送られる(URLには出ない)。 | データの送信・変更(フォームの送信、登録、更新、削除など)。 |
重要:二重送信の防止(PRGパターン)登録・更新といったPOST処理の後は、必ずreturn "redirect:/..."でGETリクエストにリダイレクトし、ブラウザの「戻る」「再読み込み」による二重送信を防ぐようにしましょう。
1-3. HTMLとThymeleafの連携パスの書き方
HTMLでControllerにリクエストを送る際のパス(URL)の書き方です。
-
HTMLの静的ファイル参照:
staticフォルダ内のCSSやJSを参照する場合は、th:hrefやth:srcを使用します。- 例:
<link rel="stylesheet" th:href="@{/css/style.css}" />
- 例:
-
Controllerへのリクエスト:
th:actionを使うことで、@{...}内のパスをルートパス(コンテキストパス)から始まる絶対パスとして自動で解釈してくれます。- 例:
<form th:action="@{/account/register/confirm}" method="post">
- 例:
Part 2: データの流れ(フォーム処理とスコープ)
ユーザーからの入力(フォーム)をControllerが受け取り、次にどこまでそのデータを保持するか(スコープ)を定義します。
2-1. フォームデータの受け取り方(JavaBean/Formクラス)
Controllerのメソッドで複数のフォームパラメーターを一括で受け取るために、JavaBeanのルールに則ったFormクラスを作成します。
| 受け取り方法 | 説明 |
|---|---|
| JavaBeanクラス | フォームのname属性と同じ名前のフィールドを持つクラスを作成し、@ModelAttributeを付与した引数として受け取る。内部的に、対応するフィールドのsetterメソッドに値がセットされます。 |
【必須ルール】JavaBeanの命名規約
- フィールド名(Java側)は
userName(キャメルケース)。 - 対応する
getter/setterメソッドを持つ。 - 引数のないコンストラクタを持つ。
2-2. データの保持範囲(スコープ)
データがどこまで生きているか(保持されるか)を理解することは、画面遷移を制御する上で重要です。
| スコープ | 説明 | Springでの扱い方 |
|---|---|---|
| リクエスト | 1回のリクエスト発生からレスポンスを返すまでの短い範囲。リダイレクト後は消滅。 |
Modelクラスを使用し、model.addAttribute("キー", 値)で登録する。 |
| セッション | クライアント(ブラウザ)ごとに紐づき、複数のリクエストをまたいで半永続的にデータを保持。 |
HttpSessionクラスを使用し、session.setAttribute("キー", 値)で登録する。 |
| スコープ | Controllerでの引数 | Thymeleafでの呼び出し方 |
|---|---|---|
| リクエスト | (Model model) |
<div th:text="${キー}"></div> |
| セッション | (HttpSession session) |
<div th:text="${session.キー}"></div> |
Part 3: 役割分担の明確化(MVCと@ Service)
Spring BootではControllerにすべての処理を書くのではなく、役割を明確に分担します。
| アノテーション | 役割 | 主な担当処理(やること) | 避けるべき処理(やらないこと) |
|---|---|---|---|
@Controller |
交通整理役 | 画面遷移の制御、リクエスト/レスポンスの受け渡し、サービスクラスの呼び出し。 | 複雑な計算、データベース操作、業務ルールの判定。 |
@Service |
業務実行役 | 複雑な制御(ビジネスロジック)、データの加工、データベース操作、業務ルールの適用。 | 直接的なリクエストのハンドリングや画面遷移の指示。 |
★重要:依存性注入(DI)@Autowiredアノテーションは、ServiceクラスなどSpringが管理しているコンポーネント(Bean)をControllerなどで自動的に結びつける(使えるようにする)ために使われます。
Part 4: データ操作の核(JPA/RepositoryによるCRUD)
Webアプリの心臓部であるデータベース操作を、Javaのオブジェクトを通じて行う仕組み(JPA)について解説します。
4-1. エンティティとリポジトリの役割
-
エンティティ(
@Entity): データベースのテーブル構造に対応するJavaクラス。レコードのデータを一時的に保持する。 -
命名: フィールド名は
user_nameではなくuserNameといったキャメルケースを意識する。DB物理名と異なる場合は@Column(name="DB物理名")で対応。 -
リポジトリ(
@Repository): エンティティを引数に取り、データベースに対するCRUD(作成・読み取り・更新・削除)処理を実行するインタフェース。
4-2. データベース接続設定
application.propertiesにJDBCドライバ情報と接続情報を設定します。
※例のコードはMYSQLを使用する前提で書かれています。DBごとに異なるので注意してください
| 内容 | コード |
|---|---|
| ドライバクラス名 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver |
| データベースの URL | spring.datasource.url=jdbc:mysql://localhost:3306/{使用したいDB名} |
| ユーザ名とパスワード |
spring.datasource.username={DBのユーザー名} spring.datasource.password={自分で決めたパスワード}
|
4-3. CRUDの基本とシーケンス(IDENTITY戦略)
リポジトリはJpaRepository<エンティティ名, 主キーの型>を継承することで、以下の基本メソッドが使用可能になります。
| 処理 | 使用メソッド | 補足 |
|---|---|---|
| 全件検索 | findAll() |
レコードを全件検索する。 |
| 主キー検索 | getById(ID) |
指定された主キーに該当するレコードを検索する。 |
| 登録・更新 | save(エンティティ) |
主キーに値がない場合は登録、主キーに値がある場合は更新となる。 |
| 削除 | deleteById(ID) |
指定された主キーに該当するレコードを削除する。 |
【重要】IDの自動生成(IDENTITY戦略)
- DB側で主キーに
auto_incrementを設定している場合、エンティティの主キーフィールドに@GeneratedValue(strategy = GenerationType.IDENTITY)を指定するだけで、IDの自動生成が有効になります。 -
ポイント:
save()実行後、戻り値のエンティティには自動生成されたIDがセットされた状態で返されます。
4-4. 外部参照とリレーション(@ ManyToOne)
リレーションを扱う際は、SQLのJOINを使わずにオブジェクト指向的に処理します。
| アノテーション | 役割 | 意味(今回の例:ItemがCategoryを持つ) |
|---|---|---|
@ManyToOne |
関連の定義 | 多数側(Item)から一側(Category)への関連を定義する。 |
@JoinColumn |
結合列の指定 | Javaフィールド(Categoryオブジェクト)とDBの外部キー列(category_idなど)を結びつける。 |
【Viewでの参照】
エンティティが規定通りだと、Thymeleafでth:text="${item.category.name}"のように、オブジェクトのフィールドを直接辿って参照できます。(内部で自動的にJOIN処理が行われているイメージ)
4-5. メソッド名による条件検索と並べ替え
JpaRepositoryのインターフェース内に、特定の命名規則に従ったメソッドを定義するだけで、SQLを自動生成させることができます。
| キーワード | 使い方 | SQLのイメージ |
|---|---|---|
findBy |
findBy[フィールド名]And[フィールド名]... |
WHERE ... AND ... |
OrderBy |
findBy...OrderByAgeDesc() |
ORDER BY age DESC |
Containing |
findByNameContaining("太郎") |
WHERE name LIKE '%太郎%' |
existsBy |
existsByEmail(email) |
検索結果が存在するか否か(boolean)を返す。 |
Part 5: 必須の防御策(入力チェック/Validation)
ユーザーが予期しないデータを送ってきても、アプリが壊れないように守るための仕組みです。
5-1. Validation用Formクラスの作成
- Formクラスに
@NotNullや@Sizeなどのアノテーションを付与し、入力チェックのルールを定義します。 -
Formクラスはバリデーションの役割、エンティティクラスはDBアクセス(データ保持)の役割と明確に分担します。
| アノテーション | 役割(チェック内容) | 補足 |
|---|---|---|
@NotNull |
nullでないか。 |
ラッパークラス(Integerなど)の未入力チェックに使う。 |
@NotBlank |
null、空文字、空白のみでないか。 |
主にString型に使う。 |
@Size(max=...) |
文字数/桁数が指定範囲内か。 | |
@Pattern(regexp=...) |
指定された正規表現のパターンと一致するか。 | 半角英数字のみ、といった形式チェックに使う。 |
5-2. Controllerでの使い方
Controllerのメソッド引数に以下の2つを順番通りに指定します。
-
@Valid @ModelAttribute Formクラス form: バリデーション対象のFormクラス -
BindingResult result: チェックの結果(エラー情報)が格納されるクラス
@RequestMapping(path = "/register", method = RequestMethod.POST)
public String doRegister(
@Valid @ModelAttribute LoginFormWithValidation form,
BindingResult result, // ★この順番が重要!
HttpSession session) {
// 1. エラーがあるか判定
if (result.hasErrors()) {
// エラーがあった場合、フォーム入力画面に戻る
return "session/loginWithValidation";
}
// 2. エラーがなければ、Serviceを呼び出し処理を進める
// ...
}
5-3. Viewでのエラーメッセージ表示
Thymeleafでは、th:errors属性を使うことで、対応するフィールドのエラーメッセージを自動で表示できます。
ユーザ ID:<input type="text" th:field="*{userId}" />
<span th:errors="*{userId}"></span><br/> <!-- ここにエラーメッセージが表示される -->
まとめ:Spring Bootは怖くない!
Spring Bootは覚えることが多いように見えますが、今回まとめたように、「設定」→「データフロー」→「役割分担」→「CRUD」→「防御」という流れを掴めば、一つのWebアプリの裏側は確実に作れます。
この記事が、Spring Bootを始めたばかりの皆さんの「羅針盤」となり、最短距離で開発を成功させる一助となれば幸いです。