【问题标题】:JSR-303 Bean Validation - Custom Constraint Multiple Annotations to One ValidatorJSR-303 Bean Validation - 一个验证器的自定义约束多个注释
【发布时间】:2012-04-13 09:26:36
【问题描述】:

在编写自定义约束时,可以通过一个验证器实现来验证多个注释。例如,我有几个注释,它们规定了不同的 @size 注释,但我希望它们都指向同一个验证器类,该验证器类进行一些全局检查,即所有都必须匹配某个正则表达式。据我所知,该实现采用一种注释类型。

一个注释

@Target( { METHOD, FIELD, ANNOTATION_TYPE, TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {UCNValidator.class})
@Documented
@Size(min = 9, max = 9, message = "{exactlength}")
public @interface UCN {

    String message() default "{invalidFormat}";

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

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

    String fieldName() default "ucn";

}

验证器

public class UCNValidator implements ConstraintValidator<UCN, String>
{

    private String pattern = "[a-zA-Z].*";
    private String fieldName;

    @Override
    public void initialize( UCN constraintAnnotation )
    {
        this.fieldName = constraintAnnotation.fieldName();
    }

    @Override
    public boolean isValid( String value, ConstraintValidatorContext constraintValidatorContext )
    {

        if ( value != null )
        {
            if ( !value.matches(pattern) )
            {
                //do some stuff
                return false;
            }

        }

        return true;

    }

【问题讨论】:

  • 决定这无论如何都不是最好的方法。对于通用验证功能,我可以编写一个所有验证器都使用的通用方法。

标签: java bean-validation


【解决方案1】:

在验证对象的一个​​属性时,似乎没有办法从对象访问其他值。我使用的解决方案是将注释放在类上,然后验证器将获取整个对象以进行验证,您可以仅访问执行验证所需的信息。

这是我写的一个比较对象的两个不同属性的文章:

@Target(TYPE)
@Retention(RUNTIME)
@Constraint(validatedBy = LessThanValidator.class)
@Documented
public @interface LessThan {

    String message() default "{com.bullethq.constraints.LessThan}";

    String bigValueProperty();

    String littleValueProperty();

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

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

那么验证器类是:

public class LessThanValidator implements ConstraintValidator<LessThan, Object> {

    private LessThan constraint;

    public void initialize(LessThan constraintAnnotation) {
        constraint = constraintAnnotation;
    }

    public boolean isValid(Object object, ConstraintValidatorContext cvc) {
        Object bigValue = getValue(object, constraint.bigValueProperty());
        Object littleValue = getValue(object, constraint.littleValueProperty());

        // If one of the values is null, then we do not perform validation.
        if (bigValue == null || littleValue == null) {
            return true;
        }

        if (bigValue instanceof Comparable && littleValue instanceof Comparable) {
            boolean valid = ((Comparable<Object>) bigValue).compareTo(littleValue) > 0;
            if (!valid) {
                // If the values are not valid, then build a custom violations which has the correct path in it.
                cvc.buildConstraintViolationWithTemplate(cvc.getDefaultConstraintMessageTemplate())
                        .addNode(constraint.littleValueProperty())
                        .addConstraintViolation().disableDefaultConstraintViolation();
            }
            return valid;
        }
        throw new IllegalArgumentException("Properties " + constraint.bigValueProperty() + " and " + constraint.littleValueProperty() + " both need to be comparable in " + object.getClass());
    }
}

getValue() 方法只是一个使用反射从对象中获取值的静态方法。

【讨论】:

  • 如果你能把getValue的代码贴出来会大有帮助
猜你喜欢
  • 1970-01-01
  • 2012-04-05
  • 1970-01-01
  • 1970-01-01
  • 2012-03-30
  • 2012-08-20
  • 1970-01-01
  • 2015-01-10
  • 1970-01-01
相关资源
最近更新 更多