[Spring Boot] バリデーションに順番をつける

JavaSpringBoot

アノテーションによる Bean バリデーションチェックを順番に実行する方法。デフォルトだと、付与しているアノテーションのバリデーションチェックはすべて同時に実行される。これを @NotBlank チェックに通ったら、次に @Pattern(regexp=xxx) のチェックを実行、みたいにしたい。

@GroupSequence を使う

グルーピング用インターフェースを作る。

public class Groups {

  public interface First {
  }

  public interface Second {
  }

  public interface Third {
  }
}

バリデーショングループに @GroupSequence を付与

バリデーショングループに @GroupSequence で順番を指定する。

@GroupSequence({Default.class, First.class, Second.class, Third.class})
public interface MailSequence {

}

バリデーション対象の Bean

バリデーションしたいフィールドに、 グルーピング用インターフェースを指定する。

public class User {

    @NotBlank
    @Length(max = 20)
    private String name;

    @NotBlank(groups= UpdateSample.class)
    @Size(min = 5, max = 128)
    @Pattern(regexp=xxx, groups = First.class)
    @CustomValidationA(groups = Second.class)
    @CustomValidationB(groups = Third.class)
    public String mail;    
}

Controller

Controller@GroupSequence を付与したグループを指定する。

@RestController
public class SampleController {

  // ➀
  @PostMapping
  public void create(@Validated({MailSequence.class}) @RequestBody User user) {
    // …
  }

  // ➁
  @PutMapping
  public void update(@Validated({UpdateSample.class, MailSequence.class}) @RequestBody User user) {
    // …
  }

}

バリデーションの動き

Controller① のパターン
@NotBlank 以外のバリデーションチェックが動く。

Controller➁ のパターン
すべてのバリデーションチェックが動く。

注意すべき動き
@GroupSequence({Default.class, First.class, Second.class, Third.class}) のように Default.class を 1 番に指定しても、 Default.classFirst.class のバリデーションチェックは同時に実施される。なので、ここでは、 @Size@Pattern のバリデーションチェックは同じタイミングとなる。

Default.class に注意

Controller① のパターン
Default.class である @Size も動く。これは、@GroupSequenceDefault.class を含めているため。@GroupSequence({First.class, Second.class, Third.class}) とすると、 Default.class@Size バリデーションチェックは動かない。

Controller➁ のパターン
すべてのバリデーションチェックが動くのは、 UpdateSampleDefault を継承しているため。 Default を継承していない場合には、 Default.class である @Size は動かない。

public static interface UpdateSample extends Default {}

バリデーショングループの実行制御について、以下で図としてまとめられている。

Posted by Agopeanuts