バリデーションのグループ化

本日のお題

今回は息抜き回です。

バリデーションのグループ分けというものをやっていきます。

 

前回まで作成していたバリデーションですが、少し数が多くなってしまいました。

あまりないかもしれませんが、全てのバリデーションに同時に引っかかった場合などに、全てのメッセージが同時に表示されるとかなり見づらくなってしまいます。

 

なので、バリデーションを2つのグループに分けて第一グループを全てクリアした場合にのみ2つ目のバリデーションが実行されるようにしたいと思います。

 

こうすれば、同時に表示されるエラーメッセージは最大でも半分になるので、それまでよりはマシになるのかなと思います。

目次

  • インターフェースの作成
  • インターフェースの編集
  • フォームを定義しているJavaクラスの編集
  • コントローラの編集

インターフェースの作成

まずは、formディレクトリの中にインターフェース用のファイルを3つ作成します。

インターフェースについては、こちらに詳しくまとめてあるので今回は説明しませんが、簡単に言うと抽象クラスの親戚みたいなものです。

 

今回は、バリデーションを2つのグループに分けるので、グループ1, 2それぞれに対応したインターフェースと、両者の実行順序を管理するためのインターフェースの計3つを作成します。

ファイル名については何でも大丈夫ですが、今回は

  • GroupOrder.java(順番管理用)
  • ValidGroup1.java(グループ1管理用)
  • ValidGroup2.java(グループ2管理用)

としておきます。

次に、インターフェースを編集していきます。

インターフェースの編集

インターフェースの編集とはいっても、ValidGroup1, 2に関してはほとんどすることはありません。

ValidGroup1.java

package com.example.demo.hello.form;

public interface ValidGroup1{
    // 何も書かない 

}

ValidGroup2に関しても同じなので省略します。

 

GroupOrder.javaには、両者の実施順序を書いていきます。

GroupOrder.java

package com.example.demo.hello.form;

import javax.validation.GroupSequence;

@GroupSequence(ValidGroup1.class, ValidGroup2.class)

public interface GroupOrder{}

 

@GroupSequenceアノテーションの中でバリデーションの実行順序を規定しています。

.classを忘れないように注意しましょう。

これで、ValidGroup1に所属しているバリデーションを先に実行することに決まりました。

ただ、どのバリデーションがValidGroup1に所属しているのかはまだ決まっていません。

なので、SignupForm.javaを編集して、バリデーションをグループと対応させていきます。

SignupForm.javaの編集

では、バリデーションをグループ分けしていきます。

方法は単純で、以下のようにカッコ内でグループを指定するだけです。

例)

@NotBlank(groups = ValidGroup1.class)

@Min(value = 4, groups = ValidGroup2.class)

上記の記述を追加するに当たって、importなどは特に必要ありません。

今回も末尾の.classを忘れないようにしましょう。

 

注意点があるとすれば、@Minや@Maxなどの引数が一つだけあるバリデーションをグループ分けする場合ですね。

この場合は、@Min(4)などと書いていた部分をvalue = 4 の形に直して、何の引数であることを明示してあげてください。

ここまできたらグループ分けはOKです。

最後にコントローラを編集します。

コントローラの編集

// GroupOrder.javaのimport

import com.example.demo.hello.form.GroupOrder;

// GroupOrder.javaの適用

public String postSignup(Model model, Locale locale, @ModelAttribute @Validated(GroupOrder.class) SignupForm form, BindingResult bindingResult){

.....以下変更なしのため省略....

}

@Validated アノテーションの引数としてGroupOrder.classを与えることで、このインターフェースで定義した順番を適用しています。