AIによる要約
Spring Bootの入力値は、URLの一部なら@PathVariable、クエリ文字列なら@RequestParam、JSONボディなら@RequestBody、HTMLフォームならFormクラスで受けるのが基本です。値がどこから来るかを見ると迷いにくくなります。


Spring BootのControllerでは、リクエストから値を受け取る方法が複数あります。
利用者管理のControllerを例にします。10 が「どの利用者か」を表すときはパスに置き、tanaka が「一覧の絞り込み」を表すときはクエリに置きます。登録する内容は、APIならJSON、HTML画面ならフォームの本文として送ります。
この記事のポイント
- URLの一部は
@PathVariableで受ける - クエリ文字列や単発のフォーム値は
@RequestParamで受ける - JSONのリクエストボディは
@RequestBodyで受ける - HTMLフォームの複数項目はFormクラスで受ける
実行用サンプル
利用者管理を題材に、パス・クエリ・JSON本文・HTMLフォームを比較します。 ソース全文、JUnitの検証コード、curlの実行ファイル、pom.xml、READMEを収録しています。JDK 17とMaven 3.9系で mvn test を実行します。Spring Boot 3.5.16のサンプルです。
まず入力値がどこにあるかを見る
Springのアノテーションを暗記しようとすると混乱します。先に見るべきなのは、入力値がHTTPリクエストのどこに入っているかです。
- パスのID。
/api/users/10の10 - クエリの検索語。
/api/users?keyword=tanakaのkeyword - HTMLフォーム: 画面の入力欄からPOSTされる値
- JSONボディ: APIクライアントから送られるJSON
ブラウザーの開発者ツールで、Request URL、Query String Parameters、Request PayloadまたはForm Data を順に見ます。たとえば name がPayloadのJSONにあれば、このサンプルでは @RequestBody で受け取ります。
@PathVariableはURLの一部を受ける
@PathVariableは、URLのパスに含まれる値を受け取ります。詳細画面、編集画面、削除処理など、対象リソースをURLで表すときによく使います。
UserInputController.java の抜粋。パスの利用者IDを受ける
@GetMapping("/api/users/{userId}")
public ResponseEntity<UserView> detail(@PathVariable("userId") long userId) {
return ResponseEntity.of(userService.find(userId));
}GET /api/users/10 はパスの 10 を long の userId として受け、利用者10を返します。/api/users/tanaka では long に変換できず、400になり詳細取得は呼ばれません。
@RequestParamはクエリ文字列や単発の値を受ける
@RequestParamは、URLの後ろにつくクエリ文字列や、単発のフォーム値を受け取るときに使います。
UserInputController.java の抜粋。クエリの検索語とページ番号を受ける
@GetMapping("/api/users")
@ResponseBody
public List<UserView> search(@RequestParam(name = "keyword", defaultValue = "") String keyword,
@RequestParam(name = "page", defaultValue = "1") int page) {
return userService.search(keyword, page);
}GET /api/users?keyword=tanaka&page=1 は検索条件をクエリで渡し、Tanakaを含む一覧を返します。page を省略すると1です。page=abc は int に変換できず、検索に進みません。
@RequestBodyはJSONを受ける
@RequestBodyは、リクエストボディのJSONをJavaオブジェクトへ変換します。画面フォームではなく、REST APIでよく使われます。
UserInputController.java の抜粋。本文のJSONを受ける
@PostMapping(path = "/api/users", consumes = APPLICATION_JSON_VALUE)
public ResponseEntity<UserView> create(@Valid @RequestBody UserCreateRequest request) {
UserView user = userService.create(request.name(), request.email(), request.notificationLimit());
return ResponseEntity.created(URI.create("/api/users/" + user.id())).body(user);
}POST /api/users は下のJSONを本文から読みます。登録に成功すると201と Location が返り、そのURLから登録した利用者を取得できます。
create-user.json の全文
{
"name": "Suzuki",
"email": "suzuki@example.com",
"notificationLimit": 5
}HTMLフォームはFormクラスで受けることが多い
Thymeleafなどの画面フォームでは、Formクラスで受ける形がよく使われます。入力値が複数あり、エラー時に画面へ戻す必要があるからです。
UserInputController.java の抜粋。HTMLフォームの項目を受ける
@PostMapping(path = "/users", consumes = APPLICATION_FORM_URLENCODED_VALUE)
public String register(@Valid @ModelAttribute("registration") UserRegistrationForm form,
BindingResult errors) {
if (errors.hasErrors()) {
return "users/new";
}
userService.create(form.name(), form.email(), 10);
return "redirect:/users/new";
}POST /users のフォーム本文では name=Sato&email=sato%40example.com のように値を送ります。@ModelAttribute が入力をFormへ割り当てます。形式が不正なメールアドレスは保存せず、入力とエラーを表示します。
使い分けを表で整理する
| 送る値 | HTTPリクエスト内の位置 | Controllerの受け口 |
|---|---|---|
利用者ID 10 | GET /api/users/10 のパス | @PathVariable("userId") |
検索語 tanaka とページ 1 | GET /api/users?keyword=tanaka&page=1 のクエリ | @RequestParam |
登録内容 name、email、notificationLimit | POST /api/users のJSON本文 | @RequestBody UserCreateRequest |
| 氏名とメールアドレス | POST /users のURLエンコードされた本文 | @ModelAttribute UserRegistrationForm |
サンプルを展開し mvn spring-boot:run で起動してから、別のターミナルで展開先へ移動して試します。上から順に、利用者詳細200、検索一覧200、API登録201、画面登録302を返します。
locations.sh の抜粋。入力の位置が異なる4リクエスト
base_url="${BASE_URL:-http://localhost:8080}"
# パスの10が利用者ID
curl -si "$base_url/api/users/10"
# クエリのkeywordとpageが検索条件
curl -si "$base_url/api/users?keyword=tanaka&page=1"
# 本文にJSONを送る
curl -si "$base_url/api/users" \
-H 'Content-Type: application/json' \
--data-binary @requests/create-user.json
# 本文にURLエンコードしたフォームの値を送る
curl -si "$base_url/users" \
--data-urlencode 'name=Sato' \
--data-urlencode 'email=sato@example.com'現場でよくある間違い
注意点
- JSONを
@RequestParamで受けようとして値が入らない /api/users/10の10を、クエリを読む@RequestParamで探してしまう- 登録フォームを大量の
@RequestParamで受けてしまう @RequestBodyにHTMLフォームの送信値が入ると思い込む
この記事とあわせて読みたい
まとめ
Spring Bootの入力値の受け取り方は、アノテーション名から覚えるより、リクエストのどこに値があるかで整理すると迷いにくいです。
URLの一部なら@PathVariable、クエリなら@RequestParam、JSONなら@RequestBody、画面フォームならFormクラス。この基本を押さえるだけで、現場コードはかなり読みやすくなります。



