あなたもこんな経験ありませんか?
Spring Boot を使って Web アプリを作っていると、「値がコントローラーに届かない」「POST しても null が返ってくる」など、パラメータ受け取りでつまずいたことはありませんか?
たとえば、フロントエンドから JSON を POST しているのに、@ModelAttribute を使ってもうまく値が入らない。逆に、HTML フォームから送っているのに、@RequestBody をつけたら 400 エラーになった……。そんな経験、エンジニアには一度はあるはずです。
この記事では、
-
@ModelAttribute
-
@RequestParam
-
@RequestBody
の違いや役割、それぞれがどういう場面に向いているのかを、実務レベルの例とともに整理していきます。読めば、「あれ、これどれ使えばいいんだっけ?」という迷いがスッキリするはずです。
なぜうまく受け取れないのか?それぞれの仕組みを理解しよう
送信形式とアノテーションの対応表
-
HTML フォーム送信(application/x-www-form-urlencoded) → @ModelAttribute
-
クエリパラメータ(URL?name=〜) → @RequestParam
-
JSON(application/json) → @RequestBody
この対応表を頭に入れておくだけでも、トラブルの多くを防げます。
@ModelAttribute の仕組みと使いどころ
@ModelAttribute は主に HTML フォーム送信で使われます。Spring MVC がリクエストの各パラメータを Java オブジェクトのプロパティにマッピングします。
@PostMapping("/register")
public String registerUser(@ModelAttribute UserForm form) {
// form.getName(), form.getEmail() などが使える
return "success";
}
ポイント:フォーム送信で null になるなら、まず @ModelAttribute が正しく使われているかを確認しましょう。Setter が不足していたり、プロパティ名が一致していないとバインドされません。
@RequestParam の仕組みと使いどころ
単一のパラメータを受け取りたいときに使います。たとえば検索画面やページングなどに。
@GetMapping("/search")
public String search(@RequestParam String keyword) {
// URL: /search?keyword=hello
return "result";
}
ポイント:必要以上に DTO にバインドしなくてもよい場面では @RequestParam が便利です。
@RequestBody の仕組みと使いどころ
@RequestBody は JSON をオブジェクトにバインドするために使います。API 開発では最も一般的です。
@PostMapping("/api/users")
public ResponseEntity<?> createUser(@RequestBody UserDto user) {
return ResponseEntity.ok().build();
}
ポイント:リクエストヘッダーに Content-Type: application/json を必ず含めましょう。含まれていないと @RequestBody が機能しません。
ありがちなつまずきと、正しい使い分けパターン
ケース 1:JSON を送ってるのに @ModelAttribute を使っている(Spring @ModelAttribute null)
NG 例:
@PostMapping("/api/users")
public ResponseEntity<?> create(@ModelAttribute UserDto user) {
return ResponseEntity.ok().build(); // user は null
}
正しい使い方:
@PostMapping("/api/users")
public ResponseEntity<?> create(@RequestBody UserDto user) {
return ResponseEntity.ok().build();
}
ケース 2:HTML フォームなのに @RequestBody を使っている(Spring @RequestBody null)
NG 例:
@PostMapping("/register")
public String register(@RequestBody UserForm form) {
return "success"; // 400 Bad Request
}
正しい使い方:
@PostMapping("/register")
public String register(@ModelAttribute UserForm form) {
return "success";
}
ケース 3:クエリパラメータを DTO にバインドしている
NG 例:
@GetMapping("/search")
public String search(@ModelAttribute SearchForm form) {
return "result";
}
正しい使い方:
@GetMapping("/search")
public String search(@RequestParam String keyword) {
return "result";
}
この記事のまとめと、次に役立つ知識
◆ 要点まとめ
-
@ModelAttribute:フォーム送信(HTML)向け
-
@RequestParam:URL クエリや単体の値向け
-
@RequestBody:JSON を使う API 向け
-
送信形式とアノテーションの整合性が超重要
◆ 次に学ぶと役立つトピック
-
@Valid と BindingResult の使い方
-
@RequestPart によるファイル受信
-
Spring Security における CSRF 設定と JSON API の相性
このような知識を積み上げていくことで、より堅牢で理解しやすい Web API が作れるようになります。
現場志向のエンジニアが、今日の悩みを明日の武器に変えられるよう、今後も役立つ技術記事を届けていきます。また読みに来てくださいね!
【外部リンク】
Spring Framework公式ガイド – Spring MVC
【内部リンク】
【Spring Boot実践ガイド】List型・Map型の違いとBeanクラスの基礎&応用
Spring Boot バリデーション入門|MVC統合とカスタムアノテーション実践例
Spring Bootで理解するGETとPOSTの違い|Thymeleaf実装例付きで初心者の画面遷移・エラー対応まで丁寧解説