クエリパラメータの受け取り
このレッスンでは、@RequestParam でクエリパラメータを受け取り、必須かどうかと既定値を制御できるようになります。
クエリ文字列とは何か
URL のうち、疑問符から後ろの部分をクエリ文字列と呼びます。
プレーンテキスト
/users?page=2&size=10&sort=nameここでは page が 2、size が 10、sort が name です。key=value の組をアンパサンドでつないだだけの、とても素朴な形式です。パス変数が「どのリソースか」を決めるのに対し、クエリパラメータは「その集合をどう見せるか」を調整します。
@RequestParam で受け取る
Java
@GetMapping("/users")
public List<UserResponse> list(@RequestParam int page,
@RequestParam int size) { ... }@PathVariable と同じように、名前が一致するパラメータが引数に入ります。文字列から int への変換も Spring が行います。名前を変えたい場合は @RequestParam("page") int pageNumber のように書きます。
required と defaultValue
ここからが本題です。@RequestParam は既定で 必須 です。パラメータが無いリクエストが来ると、そのまま 400 になります。
Java
@RequestParam int page // 必須。無ければ 400
@RequestParam(required = false) Integer page // 任意。無ければ null
@RequestParam(defaultValue = "1") int page // 無ければ 1 が入る2 番目に注意が必要です。required = false にした場合、値が無いときに null が入るので、受け取る型は int ではなく Integer にしなければなりません。int のままだと null を代入できず落ちます。
3 番目の defaultValue を指定すると、required は自動的に false 扱いになります。既定値があるのだから必須にする意味がないからです。ページングのように「指定されなければ 1 ページ目の 20 件」と決まっているものは、この形が一番読みやすくなります。
| 書き方 | パラメータあり | パラメータなし |
|---|---|---|
@RequestParam int page | その値 | 400 エラー |
@RequestParam(required = false) Integer page | その値 | null |
@RequestParam(defaultValue = "20") int size | その値 | 20 |
既定値は文字列で書く
defaultValue = "20" のように、数値でも文字列で書きます。アノテーションの属性値として使えるのが定数式に限られるため、Spring は一度文字列で受け取ってから引数の型へ変換する、という設計になっています。defaultValue = 20 とは書けないので覚えておいてください。
パラメータをまとめて受け取る
パラメータが増えてきたら、専用のクラスにまとめる書き方もあります。
Java
@GetMapping("/users")
public List<UserResponse> list(UserSearchCondition condition) { ... }アノテーションを付けずにオブジェクトを引数に取ると、Spring は同名のプロパティへセッター経由で値を詰めてくれます。検索条件が 5 つも 6 つもあるような画面では、引数を並べるよりこちらの方が読みやすくなります。
演習で確かめます
Spring では、クエリ文字列を key と value に分解して型変換し、無ければ defaultValue を入れる、という一連の処理をフレームワークが引き受けています。分解と型変換はひな形に用意済みで、今回は値の選択と既定値の適用を自分の手で書きます。page=2&size=10 のような文字列の解析結果から、page と size を選んでください。指定が欠けていたときは page が 1、size が 20 という既定値を使います。
演習で使うひな形
parseParameters("page=2") は数値の2を page の値に持つ Map を返し、parameters.get("size") は未指定なので null です。Integer で受け取ると数値と未指定を区別できます。
Java
Integer value = parameters.get("size");
int size = 20;
if (value != null) {
size = value;
}Integer の値は int にそのまま代入できます。分解と数値変換は補助メソッドに任せ、どの値を使うかを判断します。
要件
- parameters から page と size を get で取得すること
- 結果が null なら page は1、size は20を使うこと
- page=<値>,size=<値> の形で返すこと