AIによる要約
@ModelAttributeは、リクエストパラメータをFormクラスへ詰めたり、画面へ渡すモデル属性として扱ったりするために使われます。Thymeleafのフォームでは、Form名、フィールド名、Controllerの引数名がずれると値が入らない原因になります。


Spring MVCの画面フォームを触ると、@ModelAttributeというアノテーションが出てきます。
サンプルでは何となく動きますが、現場で入力値が入らない、エラー時に画面へ戻れない、初期表示でFormがない、という問題がよく起きます。
この記事のポイント
@ModelAttributeはFormとリクエスト値を結びつける- GETでは空のFormを画面へ渡すことが多い
- POSTでは入力値がFormへバインドされる
- Form名とフィールド名のずれが値が入らない原因になる
@ModelAttributeはFormをModelに載せる
@ModelAttributeは、Formクラスを画面へ渡したり、リクエストパラメータからFormへ値を詰めたりするために使われます。
@GetMapping("/users/new")
public String newUser(Model model) {
model.addAttribute("userRegisterForm", new UserRegisterForm());
return "users/new";
}
GETの初期表示では、空のFormをModelに入れて画面へ渡すことが多いです。Thymeleaf側はこのFormを使って入力欄を描画します。
POSTでは入力値がFormへ入る
POST時には、画面の入力欄のnameとFormクラスのプロパティ名が対応し、値が詰められます。
@PostMapping("/users")
public String register(@ModelAttribute UserRegisterForm form) {
userService.register(form);
return "redirect:/users";
}
実際には@ModelAttributeを省略できる場面もありますが、初学者のうちは明示して読むと、Formに値が入る流れを理解しやすいです。
Thymeleaf側の名前が重要
画面側では、th:objectとth:fieldでFormとフィールドを紐づけます。
<form th:action="@{/users}" th:object="${userRegisterForm}" method="post">
<input type="text" th:field="*{name}">
<input type="email" th:field="*{email}">
<button type="submit">登録</button>
</form>
th:objectの名前とControllerでModelに入れた名前がずれると、画面表示やエラー表示でつまずきます。
値が入らないときに見るポイント
Formに値が入らないときは、Springの仕組みを疑う前に、名前の対応を確認します。
確認ポイント
- HTMLの
name属性とFormのプロパティ名が合っているか th:objectの名前とModelの属性名が合っているか- Formクラスにsetterがあるか
- 入力欄がdisabledになっていないか
特に、画面では表示されているのにPOSTすると値が入らない場合、name属性やth:fieldの指定ミスが多いです。
BindingResultとセットで使う
入力チェックを行う画面では、@ModelAttribute、@Valid、BindingResultがセットで出てきます。
@PostMapping("/users")
public String register(@Valid @ModelAttribute UserRegisterForm form,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "users/new";
}
userService.register(form);
return "redirect:/users";
}
エラー時に同じ画面へ戻すことで、入力値とエラーメッセージを画面へ再表示できます。
現場では省略形にも出会う
Spring MVCでは、Formクラスの引数に@ModelAttributeが省略されているコードもあります。
@PostMapping("/users")
public String register(@Valid UserRegisterForm form,
BindingResult bindingResult) {
// ...
}
省略されていても、画面フォームの入力値をFormに詰める動きは同じです。ただし、学習中やチーム内で明示した方が分かりやすい場合は、明示しても構いません。
この記事とあわせて読みたい
- Spring Bootの@RequestParamとFormクラスの違いは?使い分けを解説
- BindingResultの使い方と注意点|@Validの直後に置く理由
- Spring BootのFormクラスとDTOの違いは?混ぜると困る理由を解説
まとめ
@ModelAttributeは、Formクラスと画面入力をつなぐ重要な仕組みです。GETでは画面へFormを渡し、POSTでは入力値をFormへ詰める流れで理解しましょう。
値が入らないときは、難しい原因を疑う前に、Form名、フィールド名、setter、画面側のth:fieldを確認するのが現場では近道です。
