リクエストからコントローラへの値の受け渡し(リンク・パラメータ・フォーム)
Webアプリケーションでは、ブラウザからサーバに「値」を送る場面が頻繁にある。 この章では、リンク・クエリパラメータ・パスパラメータ・フォームを用いて、値をコントローラに渡す方法を学ぶ。 実際のURLの仕組みやフォーム送信の流れを理解し、入力値をサーバ側で処理できるようになることを目指す。
学習のゴール
- クエリパラメータを
@RequestParamで受け取れる - パスパラメータを
@PathVariableで受け取れる - パスパラメータとクエリパラメータの違いと使い分けを理解できる
- HTMLフォームを使ってPOSTで値を送信し、コントローラで受け取れる
- フォームオブジェクトを定義して、複数の入力項目をまとめて扱える
- URLやフォーム送信を通して、リクエストから値を安全かつ整理された形で取得できる
クエリパラメータによる値の受け渡し
URLの「?」以降を クエリパラメータ と呼ぶ。
形式は ?key=value であり、複数の場合は & でつなぐ。
例:
http://localhost:8080/show?user=Taro
http://localhost:8080/show?user=Taro&age=20
なお、入れ替えても同じ意味になる。
http://localhost:8080/show?age=20&user=Taro
クエリパラメータとコントローラの対応
http://localhost:8080/show?user=Taro
└─── @GetMapping("/show") に対応
└─── user=Taro が @RequestParam("user") に渡される
コントローラで受け取るコード例
@Controllerpublic class ShowController {@GetMapping("/show") // /show へのGETリクエストを処理するpublic String show(@RequestParam("user") String user, // ?user=... の値を受け取る@RequestParam("age") int age // ?age=... の値を受け取る) {System.out.println(user + " さんは " + age + " 歳です。");return "display"; // templates/display.html}}
@RequestParam("user"):?user=...の値を受け取る@RequestParam("age"):?age=...の値をint型で受け取る
@RequestParam("age") int age と定義した場合、URLに ?age=abc など数字以外の文字列が来ると
Spring は自動変換に失敗して 400 Bad Request を返す。
intやInteger… 数値以外が来るとエラーString… 何でも受け取れる(自分でバリデーションが必要)
不正な入力を許容したい場合は String で受け取り、アプリ側でチェックする。
🛠️ ハンズオン演習(手順つき体験)に進む 🎯 練習問題(自力で挑戦)に進む
パスパラメータによる値の受け渡し
URLのパスに直接値を埋め込む方法を パスパラメータ と呼ぶ。
例:
http://localhost:8080/users/1
パスパラメータとコントローラの対応
http://localhost:8080/users/1
└─── {id} に対応
コントローラで受け取るコード例
@Controllerpublic class UserDetailController {@GetMapping("/users/{id}") // /users/1, /users/2 などに対応public String detail(@PathVariable("id") int id // {id} の値をint型で受け取る) {System.out.println("ユーザーIDは " + id + " です。");return "user-detail"; // templates/user-detail.html}}
クエリパラメータとパスパラメータの使い分け
どちらも「値をサーバに渡す方法」だが、役割や用途が異なる。
パスパラメータ
- どのリソースを指定するか を表すときに使う
- URLそのものが「異なるページ」として扱われる
- 例: 商品詳細ページ
https://shop.example.com/items/1https://shop.example.com/items/2
/items/1と/items/2は 別の商品ページ- キャッシュ:URLが固定なのでキャッシュが効きやすい
- SEO:検索エンジンは異なるURLを別ページとして評価するため、個別の商品や記事に最適
クエリパラメータ
- どのように表示するか、どの条件で検索するか を表すときに使う
- URLは同じページで、表示内容だけが変わる
- 例: 商品検索
https://shop.example.com/items?category=books&sort=price_aschttps://shop.example.com/items?category=music&sort=price_desc
/items?category=books&sort=price_ascと/items?category=music&sort=price_descは 同じ検索ページ- キャッシュ:パラメータの組み合わせが無数にあるため、キャッシュが効きにくい
- SEO:検索エンジンからは「同じ検索ページの派生」と見なされやすく、条件ごとに個別ページとして強く評価されにくい
「リソース=パスパラメータ」「条件=クエリパラメータ」が基本ルール
- パスパラメータ:リソースを一意に特定するために使う(ユーザーID、商品IDなど)
- クエリパラメータ:表示条件や検索オプションを指定するために使う(検索キーワード、ページ番号など)
フォームによる値の受け渡し
HTMLフォームを使って値を入力し、サーバに送る場合は通常 POSTリクエスト が使われる。
そのためコントローラ側では @PostMapping を用いる。
フォームの例
<form action="/submit" method="post"> <!-- /submit にPOSTで送信 -->
<label>名前: <input type="text" name="username"></label>
<label>年齢: <input type="number" name="age"></label>
<button type="submit">送信</button>
</form>
コントローラで受け取る例(RequestParamを使う)
@Controllerpublic class SubmitController {@PostMapping("/submit") // /submit へのPOSTリクエストを処理public String submit(@RequestParam("username") String username, // フォームの name="username" の値を受け取る@RequestParam("age") int age // フォームの name="age" の値を受け取る) {System.out.println("こんにちは " + username + " さん(" + age + "歳)");return "result"; // templates/result.html}}
フォームオブジェクトを使った受け取り
入力項目が増えると @RequestParam を1つずつ書くのは大変。
Springでは フォームオブジェクト を定義し、まとめて受け取るのが一般的。
フォームオブジェクトの置き場所
- 通常は
formやdtoといった専用のパッケージに配置する
src/main/java/com/example/demo/
├ controller/ … コントローラ
├ form/ … フォームオブジェクトを置く
│ └ UserForm.java
└ service/ … ビジネスロジック
フォームオブジェクトの例
package com.example.demo.form;public class UserForm {private String username;private int age;// getter / setter を必ず用意public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public int getAge() { return age; }public void setAge(int age) { this.age = age; }}
HTMLフォームとフィールドの対応
<form action="/submit" method="post">
<input type="text" name="username"> <!-- UserForm.username に対応 -->
<input type="number" name="age"> <!-- UserForm.age に対応 -->
<button type="submit">送信</button>
</form>
<input name="username">→UserFormのusernameフィールドに自動で値が入る<input name="age">→UserFormのageフィールドに自動で値が入る
コントローラでフォームオブジェクトを使う例
package com.example.demo.controller;import com.example.demo.form.UserForm;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.PostMapping;@Controllerpublic class SubmitController {@PostMapping("/submit")public String submit(UserForm form, Model model) {model.addAttribute("message", "こんにちは "+ form.getUsername() + " さん(" + form.getAge() + "歳)");return "result";}}
- フォームの
<input>のname属性とオブジェクトのフィールド名が一致していれば、自動で値がセットされる - 入力項目が増えても引数がシンプルに保てるため、保守性が高い
本章のまとめ
- クエリパラメータは
?key=value形式で渡し、複数は&でつなぐ @RequestParam("key")で受け取れる- パスパラメータは
/path/{id}の形式で、@PathVariableで受け取れる - 使い分け:リソースの識別はパスパラメータ、条件指定はクエリパラメータ
- フォーム送信はPOSTであり、
@PostMappingで処理する - フォームオブジェクトを使うと、
<input name="...">とフィールド名を対応させてまとめて受け取れる - 次章では、コントローラからビューへの値の渡し方と、Thymeleafの使い方を学ぶ
よくある質問
Q. @RequestParam で型変換エラーが起きないようにするには?
A. int の代わりに Integer を使い、required = false と defaultValue を組み合わせると柔軟に扱える。
@RequestParam(name = "age", required = false, defaultValue = "0") int age
Q. パスパラメータで @PathVariable を使うとき、変数名を省略できますか?
A. Java 8以降でコンパイルオプション -parameters が有効な場合、メソッドの変数名と {id} が一致していれば省略できる。
Spring Bootのデフォルト設定では省略可能な場合が多いが、明示的に書くのが推奨される。
// 省略形(推奨されないが動く場合がある)
@PathVariable int id
// 明示的な書き方(推奨)
@PathVariable("id") int id
Q. フォームオブジェクトにgetterとsetterは必須ですか?
A. 必須である。Springはフォームオブジェクトに値をセットするときにsetterを呼び出す。
setterが存在しないと、フォームから送られた値がオブジェクトに入らないため、すべて null や 0 になってしまう。
Q. POSTとGETではどちらがセキュリティ上安全ですか?
A. POSTの方が一般的に安全である。GETではパラメータがURLに含まれるため、 ブラウザの履歴・アクセスログ・リファラーヘッダーに値が残りやすい。 パスワードなどの秘密情報は必ずPOSTで送信する。