この章のゴール
@Validated を使って入力チェック(単項目検証)を有効化できるようにする
BindingResult を使って検証結果をフォームに戻す処理を理解する
@AssertTrue を使った相関項目チェック(メール再入力確認)を実装する
ここまでで、フォーム入力値を UserForm クラスで受け取れるようになった。
この章では、入力された値が正しいかをチェックする「バリデーション」を追加する。
1. バリデーション用ライブラリの追加
まず、Spring Boot で入力値の検証を行うには、Jakarta Validation API が必要である。
通常は spring-boot-starter-web に含まれているが、念のため pom.xml を確認する。
pom.xml を開き、<dependencies> タグの中に次の記述があるか確認する。
(存在しない場合は、下記を追加する)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
ポイント
<dependencies> タグは pom.xml の中央付近にある。
<dependency> のブロックは複数並んでいるが、順不同であり、どの位置に追加しても構わない。
- 記述後は必ず Spring Boot アプリを停止し、Maven install を実行 する。
- Eclipseの場合:
- 上部メニューから「実行 → 実行の停止」
- プロジェクトを右クリック → 「実行 → Maven install」
- 完了後、再度 Spring Boot を起動
UserForm クラスに単項目チェックのアノテーションを追加する。
📄src/main/java/com/example/ecsample/form/UserForm.java+ 追加- 削除
1 package com.example.ecsample.form;
2
+3 import jakarta.validation.constraints.Email;
+4 import jakarta.validation.constraints.NotBlank;
+5 import jakarta.validation.constraints.Size;
6
7public class UserForm {
- private String name;
- private String email;
- private String password;
+8 @NotBlank(message = "名前は必須です")
+9 private String name;
+10
+11 @NotBlank(message = "メールアドレスは必須です")
+12 @Email(message = "メールアドレスの形式が正しくありません")
+13 private String email;
+14
+15 @NotBlank(message = "パスワードは必須です")
+16 @Size(min = 6, message = "パスワードは6文字以上で入力してください")
+17 private String password;
ポイント
@NotBlank:空文字やスペースのみを禁止
@Email:メール形式のチェック
@Size(min=6):パスワードの長さ制限
3. Controllerで @Validated を使って検証を有効にする
@Validated を付けるだけで、UserForm に設定したアノテーションが自動でチェックされる。
📄src/main/java/com/example/ecsample/controller/UserController.java+ 追加- 削除
+import org.springframework.validation.annotation.Validated;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
@PostMapping("/register")
- public String submitForm(@ModelAttribute UserForm form, Model model) {
+ public String submitForm(@Validated @ModelAttribute UserForm form, Model model) {
System.out.println("name = " + form.getName());
System.out.println("email = " + form.getEmail());
System.out.println("password = " + form.getPassword());
model.addAttribute("form", form);
return "user/result";
}
ポイント
@Validated は Spring 独自のアノテーションで、@Valid と同様に Jakarta Validation を起動する。
- 今後グループバリデーションなどを使う可能性がある場合は、
@Validated を使用するのが推奨である。
4. 動作確認①(@Validated)
/register にアクセスし、名前を空欄のまま送信する
- ブラウザにエラー画面が表示され、
System.out.printlnの内容はコンソールに表示されないことを確認する
- これは、バリデーションのチェックは実行されているが、結果を処理していないためである
次に、BindingResult を使ってエラーを受け取り、画面に戻す処理を実装する。
5. BindingResult を追加して、エラーをフォームへ戻す
📄src/main/java/com/example/ecsample/controller/UserController.java+ 追加- 削除
@PostMapping("/register")
- public String submitForm(@Validated @ModelAttribute UserForm form, Model model) {
+public String submitForm(
+ @Validated @ModelAttribute("form") UserForm form,
+ BindingResult bindingResult,
+ Model model) {
+
+ if (bindingResult.hasErrors()) {
+ return "user/register";
+ }
System.out.println("name = " + form.getName());
System.out.println("email = " + form.getEmail());
System.out.println("password = " + form.getPassword());
model.addAttribute("form", form);
return "user/result";
}
ポイント
BindingResult は @Validated の直後に書く(順序が違うと無効)
- エラーがある場合は
bindingResult.hasErrors() が true となる
return "user/register" としてフォーム画面に戻せば、再入力できる
@ModelAttribute("form") は、フォームオブジェクトを "form" という名前で Model に登録する指定である。
これにより、Thymeleaf 側の <form th:object="${form}"> と名前が一致し、エラー時も同じオブジェクトを再表示できる。
@ModelAttribute の "form" を省略した場合、Spring はクラス名をもとに自動命名する。
たとえばクラス名が UserForm の場合は、userForm という名前で登録される。
このときはテンプレート側で <form th:object="${userForm}"> と記述すれば同じように動作する。
6. HTMLにエラーメッセージを表示する
📄src/main/resources/templates/user/register.html+ 追加- 削除
- <p>名前:<input type="text" th:field="*{name}" /></p>
+13 <p>
+14 名前:<input type="text" th:field="*{name}" />
+15 <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
+16 </p>
- <p>メールアドレス:<input type="email" th:field="*{email}" /></p>
+17 <p>
+18 メールアドレス:<input type="email" th:field="*{email}" />
+19 <span th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></span>
+20 </p>
- <p>パスワード:<input type="password" th:field="*{password}" /></p>
+21 <p>
+22 パスワード:<input type="password" th:field="*{password}" />
+23 <span th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></span>
+24 </p>
7. 動作確認②(BindingResult)
/register にアクセスし、空欄のまま送信する
- 各入力欄の下にエラーメッセージが表示されることを確認
- すべて正しく入力して送信すると、結果画面に進む
ポイント
th:errors は、対象フィールドのエラーメッセージを自動的に表示する
- メッセージ内容は
UserForm のアノテーションで指定した message 属性が使われる
8. 相関項目チェック(メール再入力確認)
次に、相関チェックとして「メール再入力欄」を追加する。
2つの入力値が一致しなければエラーとする。
📄src/main/java/com/example/ecsample/form/UserForm.java+ 追加- 削除
1 public class UserForm {
2 @NotBlank(message = "名前は必須です")
3 private String name;
4
5 @NotBlank(message = "メールアドレスは必須です")
6 @Email(message = "メールアドレスの形式が正しくありません")
7 private String email;
8
+9 @NotBlank(message = "メール確認用アドレスを入力してください")
+10 private String emailConfirm;
11
12 @NotBlank(message = "パスワードは必須です")
13 @Size(min = 6, message = "パスワードは6文字以上で入力してください")
14 private String password;
15
+16 @AssertTrue(message = "メールアドレスが一致しません")
+17 public boolean isEmailConfirmed() {
+18 return email != null && email.equals(emailConfirm);
+19 }
+20
+21 public String getEmailConfirm() {
+22 return emailConfirm;
+23 }
+24
+25 public void setEmailConfirm(String emailConfirm) {
+26 this.emailConfirm = emailConfirm;
+27 }
ポイント
@AssertTrue は クラスレベルの検証(フィールド単位ではない)。
isEmailConfirmed() が false を返すと、「メールアドレスが一致しません」というメッセージが生成される。
- メソッド名が
isEmailConfirmed であるため、Thymeleaf では *{emailConfirmed} として参照される。
② HTMLフォームを修正
@AssertTrue による検証結果は emailConfirmed という論理プロパティ名で扱われる。
したがって、確認欄の下に以下のようにエラー出力を追加する。
📄src/main/resources/templates/user/register.html+ 追加- 削除
<p>
メールアドレス:<input type="email" th:field="*{email}" />
<span th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></span>
</p>
+ <p>
+ メールアドレス(確認用):<input type="email" th:field="*{emailConfirm}" />
+ <span th:if="${#fields.hasErrors('emailConfirm')}" th:errors="*{emailConfirm}"></span>
+ </p>
+
+ <p th:if="${#fields.hasErrors('emailConfirmed')}" th:errors="*{emailConfirmed}"></p>
ポイント
isEmailConfirmed() メソッドのエラーメッセージは、Thymeleaf では emailConfirmed という名前で参照される。
th:errors="*{emailConfirmed}" と指定すると、@AssertTrue のエラーメッセージ(「メールアドレスが一致しません」)が表示される。
th:if によって、エラーが存在するときだけ <p> 要素が出力される。
9. 動作確認③(相関チェック)
- メールアドレスと確認用メール欄に異なる値を入力して送信
- 「メールアドレスが一致しません」というメッセージが表示されることを確認
- 一致させて再送信すると、エラーが消え、登録完了画面に遷移する
補足
@AssertTrue の検証結果は「論理プロパティ」として扱われるため、
th:errors="*{emailConfirmed}" のように、メソッド名から先頭の is を除いた名前で参照する必要がある。
- この仕組みにより、フィールド同士の関係を簡単に検証できる。
📘 この章での学び
@Validated で入力チェックを自動実行できる
BindingResult で検証結果を取得し、フォームへ戻す処理を学んだ
@AssertTrue により、2つのフィールドの一致確認(相関チェック)を実装できた
練習問題
- パスワードにも確認欄を追加し、2つのパスワードが一致していない場合にエラーを出すようにせよ。
- メールアドレスが「example.com」ドメインのみ許可されるように条件を追加してみよ。
Gitでコミットを作成する
git add .
git commit -m "フォーム入力値のバリデーションと相関チェックを@Validatedで実装"