Springの@ModelAttributeとBindingResultの使い方入門!初心者でもわかるフォーム値の受け取り方
生徒
「Springでフォームの入力内容をサーバー側で受け取るにはどうしたらいいですか?」
先生
「その場合は、@ModelAttributeというアノテーションを使います。バリデーション結果はBindingResultで取得します。」
生徒
「フォームの値を簡単に受け取れるってことですか?」
先生
「はい。具体的な使い方を一緒に見ていきましょう!」
1. Spring MVCでフォームの値を受け取る基本
Spring MVCでは、HTMLフォームの入力値をコントローラで受け取る方法として@ModelAttributeを使うのが一般的です。ユーザーが入力したデータは、Javaのオブジェクトにマッピングされ、そのまま使えるようになります。たとえば、名前やメールアドレスといった複数のフィールドを、1つのクラスでまとめて受け取ることができます。
2. @ModelAttributeとは?
@ModelAttributeは、フォームから送信されたパラメータをJavaのオブジェクトにバインドするためのアノテーションです。コントローラの引数に付けることで、Springが自動的にリクエストパラメータをセットしてくれます。
@PostMapping("/submit")
public String submitForm(@ModelAttribute UserForm form) {
// formオブジェクトに入力内容が格納されている
return "result";
}
上記のように書くだけで、HTMLフォームのname属性と同じ名前のフィールドに値が自動でセットされます。
3. BindingResultとは?バリデーション結果の受け取り方
フォームにバリデーションチェックを行いたい場合、@Validや@Validatedと一緒にBindingResultを使うことで、エラー情報を受け取ることができます。エラーがあるかどうかの判定や、エラーメッセージの取得に利用されます。
@PostMapping("/submit")
public String submitForm(@ModelAttribute @Valid UserForm form, BindingResult result) {
if (result.hasErrors()) {
return "form";
}
return "result";
}
このように、エラーがあれば再度フォーム画面に戻し、なければ処理を進めるという流れが作れます。
4. フォームオブジェクトの定義方法
フォームの値を受け取るためには、あらかじめオブジェクト(フォームクラス)を作成しておく必要があります。このクラスには、入力される項目と同じ名前のフィールドを定義し、必要に応じてバリデーションアノテーションも付けます。
import jakarta.validation.constraints.*;
public class UserForm {
@NotBlank(message = "名前は必須です")
private String name;
@Email(message = "正しいメールアドレスを入力してください")
private String email;
// GetterとSetter
}
このように定義したクラスが、@ModelAttributeを使って自動的にコントローラに渡されます。
5. HTML側のフォームの書き方
Thymeleafを使う場合、th:objectやth:field属性を使うことで、@ModelAttributeで受け取るオブジェクトと連携させることができます。
<form th:action="@{/submit}" th:object="${userForm}" method="post">
<label>名前:</label>
<input type="text" th:field="*{name}" />
<div class="text-danger" th:if="${#fields.hasErrors('name')}" th:errors="*{name}">名前エラー</div>
<label>メールアドレス:</label>
<input type="email" th:field="*{email}" />
<div class="text-danger" th:if="${#fields.hasErrors('email')}" th:errors="*{email}">メールエラー</div>
<button type="submit" class="btn btn-primary">送信</button>
</form>
このように、Thymeleafでは簡潔にフォームとオブジェクトをバインドでき、エラー表示もわかりやすく記述できます。
6. コントローラ全体の例
ここまでの内容をまとめて、@ModelAttributeとBindingResultを使ったコントローラの全体像を見てみましょう。
@Controller
public class FormController {
@GetMapping("/form")
public String showForm(Model model) {
model.addAttribute("userForm", new UserForm());
return "form";
}
@PostMapping("/submit")
public String submitForm(@ModelAttribute @Valid UserForm userForm, BindingResult result) {
if (result.hasErrors()) {
return "form";
}
return "result";
}
}
このコードにより、フォーム画面表示、入力値の受け取り、エラーチェックまで一通りの処理が実現できます。
7. よくあるミスと注意点
BindingResultは、@Validや@ModelAttributeの直後に記述する必要がある- フォームの
name属性とJavaのフィールド名が一致していないと値がバインドされない - HTML側の
th:objectやth:fieldの設定ミスでバリデーションが効かない
特に初心者は、バリデーションがうまく動かないときにBindingResultの位置やフォームのフィールド名を見直すと解決することが多いです。
8. 補足:@ModelAttributeの省略と明示の違い
実は、@ModelAttributeは省略することもできます。ただし、複数の引数がある場合や明示的に書いたほうが読みやすいケースも多いため、初心者のうちは付けておくのが無難です。
また、@RequestParamとの違いも混乱しやすいポイントです。@RequestParamは単一のパラメータを受け取るときに使い、@ModelAttributeは複数項目をまとめて受け取るときに便利です。