1

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

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

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

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

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

4

3 回答 3

1

The problem is that the annotations params need to have a value that can be resolved at compile time, but the Call to Calendar.getInstance().get(Calendar.YEAR) can only be resolved at runtime thus the compiler error.

You are better off in this type of situation to write the validation logic in the setter logic, something like

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

The alternative is that you can write a custom JSR 303 Annotation something like @VerifyAge(maxAge=50) then in the handler for the annotation you can check that the value is less than 50.

See http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html/validator-customconstraints.html for details on how to write a custom validation annotation.

于 2013-09-16T16:57:07.793 回答
0

If you’re using the Spring Framework then you can use the Spring Expression Language (SpEL) for that. I’ve wrote a small library that provides JSR-303 validator based on SpEL. Take a look at https://github.com/jirutka/validator-spring.

With this library you can write your validation like this:

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

However, the code to obtain the current year is quite ugly, isn’t it? Let’s put it into a helper class!

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

And then you can do this:

@SpELAssert(value="#this < #todayYear() - 50", helpers=CalendarHelper.class)
private int birthYear;
于 2014-01-03T23:23:49.170 回答
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)它应该可以工作。

于 2013-09-16T17:04:22.520 回答