JSR-303 - 计算值作为参数?

时间:2013-09-16 16:49:48

标签: java annotations bean-validation

我希望以一种方式验证字段birthYear:“用户的年龄必须低于50。”

所以我想像这样使用JSR-303注释验证:

@Max(Calendar.getInstance().get(Calendar.YEAR) - 50)
private int birthYear;

但是编译器说“属性值必须是常量。”

有没有办法以简单的方式做到这一点,比如这个?或者是否有必要为此实现我自己的验证器?

3 个答案:

答案 0 :(得分:1)

问题是注释参数需要有一个可以在编译时解析的值,但是对Calendar.getInstance().get(Calendar.YEAR)的调用只能在运行时解析,因此编译错误。

在这种情况下,最好在设置器逻辑中编写验证逻辑,例如

public  void setBirthYear( int year){ 
   if( Calendar.getInstance().get(Calendar.YEAR) - year < 50) {
   {
     throw IllegalAgumentException()
   }
   this.birthYear = year;
} 

另一种方法是你可以编写一个类似@VerifyAge(maxAge=50)的自定义JSR 303 Annotation,然后在注释的处理程序中检查该值是否小于50.

有关如何编写自定义验证注释的详细信息,请参阅http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html/validator-customconstraints.html

答案 1 :(得分:0)

正如您的错误消息所示,您不能在注释值中包含表达式,因此您需要使用自定义验证注释。

这样做相对容易:

注释

@Constraint(validatedBy = AgeConstraintValidator.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface MaxAge {

/**
 * The age against which to validate.
 */
int value();

String message() default "com.mycompany.validation.MaxAge.message";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

约束验证器

public class AgeConstraintValidator implements ConstraintValidator<MaxAge, Integer> {

private int maximumAge;

@Override
public void initialize(MaxAge constraintAnnotation) {
    this.maximumAge = constraintAnnotation.value();
}

@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
    if (value == null) {
        return true;
    }

    return value.intValue() <= this.maximumAge;
}

}

然后,您可以使用@MaxAge(50)注释您的字段,它应该可以正常工作。

答案 2 :(得分:0)

如果您正在使用Spring Framework,那么您可以使用Spring Expression Language(SpEL)。我写了一个小型库,提供基于SpEL的JSR-303验证器。看看https://github.com/jirutka/validator-spring

使用此库,您可以像这样编写验证:

@SpELAssert("#this < T(java.util.Calendar).getInstance().get(T(java.util.Calendar).YEAR) - 50")
private int birthYear;

然而,获得当年的代码相当难看,不是吗?让我们把它变成一个帮手类吧!

public class CalendarHelper {
    public static int todayYear() {
        return Calendar.getInstance().get(Calendar.YEAR);
    }
}

然后你可以这样做:

@SpELAssert(value="#this < #todayYear() - 50", helpers=CalendarHelper.class)
private int birthYear;