LoginSignup
0
0

More than 1 year has passed since last update.

Spring Bootで相関Validationを実装する(Aは入力かつBは未入力のチェック)

Posted at

はじめに

Spring Bootを使用して、フォームの値をバリデーションしたい。ただ、単一の項目ではなく、
複数の条件を指定した相関バリデーションを行いたい場合の実装を、自作アノテーションを
用いて対応したので、その備忘録を下記に残す。

今回やりたい例

あるフォーム画面にて、Aは入力していて、かつBは未入力の場合をバリデーションする。

環境

  • Java11

実装例

formクラスを作成する

testForm.java
@Setter
@Getter
@TestValidation(targetA= "targetAName", targetBName= "targetB")
public class ProfileForm {
  private String targetA;
  private String targetB;
  • Lombokを使用しているため、@Setter/@Getterを付与
  • @testValidation(targetA= "targetA", targetB= "targetB")`
    • @testValidation:後記するInterface名
    • (targetAName= "targetA", targetBName= "targetB"):左辺がformのname属性で右辺がフィールド名

独自アノテーション用のインタフェースを作成する

TestValidation.Java
@Documented
@Constraint(validatedBy = {TestValidator.class})
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ReportAsSingleViolation
public @interface TestValidation{

  String message() default "エラーメッセージ";

  Class<?>[] groups() default {};

  Class<? extends Payload>[] payload() default {};

  String targetA();

  String targetB();
}
  • @Constraint(validatedBy = {TestValidator.class})
    • 後記するバリデーションの実装クラス名

作成したアノテーションの実装クラスを作成する

TestValidator.java
public class TestValidator implements ConstraintValidator<TestValidation, Object> {

  private String targetA;
  private String targetB;
  private String message;

  @Override
  public void initialize(TestValidation constraintAnnotation) {
    this.targetA = constraintAnnotation.targetA();
    this.targetB = constraintAnnotation.targetB();
    this.message = constraintAnnotation.message();
  }

  @Override
  public boolean isValid(Object form, ConstraintValidatorContext constraintValidatorContext) {

    if (Objects.isNull(form)) {
      return true;
    }

    // formから対象項目を取得
    BeanWrapper beanWrapper = new BeanWrapperImpl(form);
    String testTargetA = (String) beanWrapper.getPropertyValue(this.targetA);
    String testTargetB = (String) beanWrapper.getPropertyValue(this.targetB);

    if (StringUtils.isNotEmpty(testTargetA) && StringUtils.isEmpty(testTargetB)) {
      constraintValidatorContext.disableDefaultConstraintViolation();
      constraintValidatorContext
        .buildConstraintViolationWithTemplate(this.message)
        .addPropertyNode(this.testTargetB).addConstraintViolation();

          return false;
    }

    return true;
  }
  • ConstraintValidator<TestValidation, Object>
    • 第一引数には、先ほど作成したInterface名を記述
    • 第二引数には、formが渡されるのでObject型を指定
  • BeanWrapper beanWrapper = new BeanWrapperImpl(form);
    • 上記記述で、formから欲しい値を取得

以上。
走り書きなので、追記するかもしれないです。

参考URL

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0