Bean验证:复杂的消息值解析 - 但如何?

时间:2013-01-15 11:02:32

标签: java bean-validation

我编写了一个名为@Year的自定义约束,用于检查某个年份是否发生Date

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Constraint(validatedBy = YearCheck.class)
public @interface Year {

  String message() default "{year.message}";

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

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

  /**
   * The lower year. If not specified then no upper boundary check is performed.<br>
   * Special values are:
   * <ul>
   * <li>{@link TimeUtil#NOW} for the current year
   * </ul>
   */
  String min() default "";

  /**
   * The upper year. If not specified then no upper boundary check is performed.<br>
   * Special values are:
   * <ul>
   * <li>{@link TimeUtil#NOW} for the current year
   * </ul>
   */
  String max() default "";
}

ValidationMessages.properties包含以下内容:

year.message = must be a year between {min} and {max}

如您所见,minmax是字符串,因为TimeUtil.NOW(包含"now"的常量)表示当前年份用于比较。< / p>

此外,如果未指定minmax,则表示相应的值为无穷大

所以,问题是,例如min:我如何检查min是否已设置且是否为数字("""now")如何设置一个值,然后将其插入到消息中?

例如@Year(min=1900,max=TimeUtil.NOW)应该生成消息

must be a year between 1900 and 2013

我已经在stackoverflow上阅读了一些答案,阅读文档,但我不确定a)是否可能b)我需要在约束实现或自定义MessageInterpolator中执行此操作。

1 个答案:

答案 0 :(得分:1)

  

如何检查min是否已设置且是否为数字

您可以在initialize()实施的ConstraintValidator方法中访问注释属性。

  

如何设置一个值,然后将其插入到消息中?

您无法直接执行此操作,但您可以使用传递的isValid()在验证程序的ConstraintValidatorContext方法中自行创建邮件。

您的验证器可能看起来像这样:

public class YearValidator implements ConstraintValidator<Year, String> {

    private Date min;
    private Date max;

    @Override
    public void initialize(Year constraintAnnotation) {
        if(constraintAnnotation.min().equals("")) {
            min = getMinimumDate();
        }
        else if(constraintAnnotation.min().equals(TimeUtil.NOW)) {
            min = getCurrentYear();
        }
        else {
            min = getYearFromString(constraintAnnotation.min());
        }

        //same for max()
}

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

        if(value.before(min) || value.after(max)) {

            context.disableDefaultConstraintViolation();

            //load/create the error message and set min and max in it
            String template = getTemplate(min, max);

            context
                .buildConstraintViolationWithTemplate(template)
                .addConstraintViolation();

            return false;
        }

        return true;
    }
}