KOJIKOJIKOJI Blog
← Prev

Next →

Spring BootでBindingResultをリダイレクト先へ渡す際の注意点

By Donna Thomason | 2021/12/09 02:23:04

要約

SpringBootアプリケーションでフォームのバリデーションを行う際、BindingResultを用いてエラーメッセージを管理することがあります。これをリダイレクト後の画面で表示するために、RedirectAttributesaddFlashAttributeメソッドを使ってBindingResultをリダイレクト先へ渡す場合、リダイレクト先のコントローラーメソッドの引数にFormクラスとBindingResultクラスを直接定義してはいけません。正しく扱わないと、予期せぬ動作やエラーメッセージが表示されないといった問題が発生する可能性があります。

SpringBootのバージョン情報

  • Spring Boot バージョン: 2.7.0 以降
  • Java バージョン: 8 以降

BindingResultをRedirectAttributesのaddFlashAttributeで渡す際の注意点

なぜリダイレクト先でFormクラスとBindingResultクラスを渡すと機能しないのか

  1. Spring MVCのリクエストライフサイクル:

    • Spring MVCでは、HTTPリクエストがコントローラーメソッドにマッピングされる際、BindingResultはフォームのバインディング処理時に新たに生成されます。このバインディング処理では、リクエストパラメータをFormオブジェクトにバインドし、その結果としてのBindingResultが自動的に生成されます。
    • リダイレクト時には、新しいHTTPリクエストが発行されるため、BindingResultも新たに生成されます。この時点で、元のリクエストで使用されたBindingResultは、リクエストスコープを超えて存在しないため、リダイレクト先では無視されます。
  2. Flash Attributesの扱い:

    • RedirectAttributes.addFlashAttributeは、一時的にデータをセッションに保存し、リダイレクト先でそのデータを取り出して利用できるようにするための機能です。しかし、リダイレクト先でFormクラスとBindingResultクラスを引数として宣言すると、Spring MVCはこれを新たなバインディングプロセスとして扱い、FlashAttributesに格納されたBindingResultを適切に利用しません。
    • 特に、BindingResultのフラッシュ属性は、"org.springframework.validation.BindingResult.フォーム名"という特定のキーで格納されますが、リダイレクト先での新しいバインディング処理が優先されてしまうため、addFlashAttributeで渡されたBindingResultは上書きされてしまい、利用されません。

誤った実装例

以下は、リダイレクト先でFormクラスとBindingResultを引数に定義してしまう誤った例です。この場合、BindingResultが適切に処理されず、リダイレクト後の画面でエラーメッセージが表示されない可能性があります。

@Controller
public class SampleController {

    @PostMapping("/submit")
    public String submitForm(@ModelAttribute("form") Form form, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
        if (bindingResult.hasErrors()) {
            redirectAttributes.addFlashAttribute("form", form);
            redirectAttributes.addFlashAttribute("bindingResult", bindingResult);
            return "redirect:/form";
        }
        // 正常処理
        return "success";
    }

    // リダイレクト先での処理
    @GetMapping("/form")
    public String showForm(@ModelAttribute("form") Form form, BindingResult bindingResult) {
        // ここではBindingResultが適切に機能しない
        return "form";
    }
}

正しい実装例

正しい実装では、リダイレクト先でBindingResultを直接引数に取らず、@ModelAttributeを用いてFormオブジェクトを取得し、それに関連付けられたエラーメッセージを取り出して表示します。

@Controller
public class SampleController {

    @PostMapping("/submit")
    public String submitForm(@ModelAttribute("form") Form form, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
        if (bindingResult.hasErrors()) {
            redirectAttributes.addFlashAttribute("form", form);
            redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.form", bindingResult);
            return "redirect:/form";
        }
        // 正常処理
        return "success";
    }

    // リダイレクト先での処理
    @GetMapping("/form")
    public String showForm() {
        return "form";
    }
}

注意点

  1. BindingResultの名前に注意:
    • RedirectAttributesにBindingResultを追加する際、キー名を"org.springframework.validation.BindingResult.フォーム名"として渡す必要があります。この例では"org.springframework.validation.BindingResult.form"です。
  2. BindingResultを直接渡さない:
    • リダイレクト先のメソッドにBindingResultを直接渡しても機能しないため、BindingResultのオブジェクトはRedirectAttributesを通じて渡します。
  3. エラーメッセージの表示:
    • BindingResultがリダイレクト先で正しく機能すれば、formに関連するエラーメッセージが正しく表示されます。

Note

Highlights information that users should take into account, even when skimming.

Tip

Optional information to help a user be more successful.

Important

Crucial information necessary for users to succeed.

Warning

Critical content demanding immediate user attention due to potential risks.

Caution

Negative potential consequences of an action.

この実装により、フォームバリデーションのエラーメッセージがリダイレクト先の画面でも適切に表示されるようになります。

← Prev

Next →

Author Image

Donna Thomason

2020年にFictitiousを創業。前職のPetlassianではマーケティング責任者としてグローバル・マーケティングを担当し、オンライン販売モデルの構築・拡大に貢献