Spring Bootの@RequestParamとFormクラスの違いを解説する記事のアイキャッチ。若手エンジニアがJava道場風の学習空間で入力値の受け取り方を学ぶイラスト。

Spring

Spring Bootの@RequestParamとFormクラスの違いは?使い分けを解説

AIによる要約

@RequestParamは単発の値を受け取るときに便利です。一方、Formクラスは画面入力や検索条件のように複数項目を1つの入力として扱いたいときに向いています。迷ったら、値が業務上ひとまとまりかどうかで判断します。

新人SE
新人SE
@RequestParamで全部受け取れば、Formクラスっていらないんですか?
ポンコツSE
ポンコツSE
少ない検索条件ならそれでもよいですが、登録画面や項目が増える検索画面ではFormクラスにまとめた方が読みやすく、レビューでも説明しやすくなります。

Spring BootのControllerを書き始めると、@RequestParamで値を受け取る書き方と、Formクラスでまとめて受け取る書き方の両方が出てきます。

初学者が迷うのは、どちらでも動いてしまう場面があるからです。動くかどうかだけで決めると、あとで入力項目が増えたときにControllerが読みにくくなります。

この記事のポイント

  • @RequestParamは単発の値や簡単な検索条件に向く
  • Formクラスは複数項目を1つの入力として扱いたいときに向く
  • 登録・更新フォームではFormクラスを使うとバリデーションしやすい
  • Controllerの引数が増えてきたらFormクラス化を検討する

@RequestParamは単発の値を受けるときに使いやすい

@RequestParamは、リクエストパラメータをControllerの引数で直接受け取るためのアノテーションです。検索キーワード、ページ番号、並び順など、単発で意味が分かる値に向いています。

@GetMapping("/users")
public String list(@RequestParam(required = false) String keyword,
                   Model model) {
    List<UserListItem> users = userService.search(keyword);
    model.addAttribute("users", users);
    return "users/list";
}

この程度なら、Formクラスを作らなくても読みやすいです。Controllerを見たときに、何を受け取っているかすぐ分かります。

Formクラスは入力項目をひとまとまりにする

一方で、入力項目が複数あり、それらを合わせて1つの検索条件や登録内容として扱うなら、Formクラスにまとめる方が自然です。

public class UserSearchForm {
    private String keyword;
    private String status;
    private String fromDate;
    private String toDate;

    // getter / setter
}

@GetMapping("/users")
public String list(UserSearchForm form, Model model) {
    List<UserListItem> users = userService.search(form);
    model.addAttribute("users", users);
    return "users/list";
}

検索条件が増えたとき、Controllerの引数を毎回増やすより、Formクラスを見れば画面の入力項目が分かる状態にしておく方が保守しやすくなります。

登録画面ではFormクラスが基本になりやすい

登録や更新の画面では、名前、メールアドレス、電話番号、住所など、複数の値がセットで扱われます。この場合はFormクラスにまとめると、入力チェックも書きやすくなります。

public class UserRegisterForm {
    @NotBlank
    private String name;

    @NotBlank
    @Email
    private String email;

    // getter / setter
}

@PostMapping("/users")
public String register(@Valid UserRegisterForm form,
                       BindingResult bindingResult) {
    if (bindingResult.hasErrors()) {
        return "users/new";
    }
    userService.register(form);
    return "redirect:/users";
}

この形にしておくと、Controllerは「入力を受け取る」「エラーなら戻す」「問題なければServiceへ渡す」という役割に集中できます。

@RequestParamだけで頑張ると何が困るか

@RequestParamを大量に並べると、メソッドの引数が長くなり、何の画面入力なのか分かりにくくなります。レビューでは、まずここを見られます。

@PostMapping("/users")
public String register(@RequestParam String name,
                       @RequestParam String email,
                       @RequestParam String phone,
                       @RequestParam String zipCode,
                       @RequestParam String address,
                       @RequestParam String departmentCode) {
    userService.register(name, email, phone, zipCode, address, departmentCode);
    return "redirect:/users";
}

このコードは動くかもしれませんが、入力チェックを追加したり、項目名を変更したりすると修正箇所が散らばります。若手が現場で触るには事故りやすい形です。

判断基準は、値が単発か、画面入力としてひとまとまりかです。単発なら@RequestParam、まとまりならFormクラスを検討します。

現場レビューではどう見られるか

// レビューコメント例
検索条件が増えているので、UserSearchFormにまとめた方が読みやすそうです。

// レビューコメント例
登録画面の入力値を@RequestParamで個別に受けていますが、
入力チェックを考えるとFormクラスに寄せた方がよいです。

レビューで大事なのは、Formクラスを使っているかどうか自体ではありません。入力値のまとまりがコード上で表現されているか、変更しやすいか、入力チェックを置きやすいかです。

レビュー前のセルフチェック

確認リスト

  • Controllerの引数が長くなりすぎていないか
  • 登録・更新フォームを@RequestParamだけで受けていないか
  • 検索条件が増える予定があるならFormクラス化を検討したか
  • Formクラスに画面入力以外の責務を持たせていないか

この記事とあわせて読みたい

まとめ

@RequestParamとFormクラスは、どちらが上位という関係ではありません。単発の値を受けるなら@RequestParam、複数項目を1つの入力として扱うならFormクラスが向いています。

新人のうちは、Controllerの引数が増えたときに一度立ち止まるだけでも十分です。入力値のまとまりを意識できると、Spring MVCのコードはかなり読みやすくなります。

-Spring
-, , , , ,