5
7

More than 5 years have passed since last update.

【Spring】自作バリデーションの作成

Last updated at Posted at 2019-05-25

やること

2項目間の値の一致チェックを行うバリデーションクラスを作成する。

はじめに

バリデーションを実装する場合は、
- バリデーションの対象に宣言する「アノテーション」
- 「アノテーション」に対してのチェック処理を行う「バリデータ」が必要。

アノテーション

CompareEquals.java
/**
 * 2項目の値の一致チェックを行う。
 */
@Constraint(validatedBy = {CompareEqualsValidator.class})
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CompareEquals {

    // バリデーションを実装する際の必須定義。
    Class<?>[]groups() default {};
    Class<? extends Payload>[] payload() default {};

    String value1();
    String value2();
    String message();

    @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {
        CompareEquals[] values();
    }
}
  • @Constraint(validatedBy = {CompareEqualsValidator.class})でバリデータクラスを指定する。
  • groups, payloadは必須項目。省略した場合は、下記例外が発生する。
    javax.validation.ConstraintDefinitionException: HV000074: com.example.demo.com.annotation.CompareValue contains Constraint annotation, but does not contain a payload parameter.

バリデータクラス

CompareEqualsValidator
/**
 *  2つのパラメタの一致判定を行う。
 */
public class CompareEqualsValidator implements ConstraintValidator<CompareEquals, Object> {

    private String value1;
    private String value2;
    private String message;

    /**
     * 初期化処理
     */
    @Override
    public void initialize(CompareEquals annotation) {
        // アノテーションの引数情報を設定する。
        this.value1 = annotation.value1();
        this.value2 = annotation.value2();
        this.message = annotation.message();
    }

    /**
     * 比較処理
     */
    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {

        // 2つの値を取得して比較する。
        BeanWrapper beanWrapper = new BeanWrapperImpl(value);
        Object value1 = beanWrapper.getPropertyValue(this.value1);
        Object value2 = beanWrapper.getPropertyValue(this.value2);

        // 比較処理
        // 同値でも型が違う場合はfalseを返却する。
        boolean matched = ObjectUtils.nullSafeEquals(value1, value2);

        if (matched) {
            return true;
        }

        // メッセージを設定する。
        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(message).addPropertyNode(this.value1).addConstraintViolation();
        return false;
    }
}
  • ObjectUtils.nullSafeEqualsはSpringのUtilityクラス
  • isValidの引数valueにはFormクラスが渡される。
  • beanWrapper.getPropertyValue()で誤ったフィールド名を渡した場合は下記例外が発生する。
    org.springframework.beans.NotReadablePropertyException: Invalid property 'aaa' of bean class [com.example.demo.app.form.TestForm]: Bean property 'aaa' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
5
7
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
5
7