无法在Spring-MVC中覆盖ConstraintValidator缺省消息

时间:2014-08-31 16:04:35

标签: java spring-mvc bean-validation hibernate-validator

使用Spring验证时,我遇到覆盖默认ConstraintValidator消息的问题。

我有一个自定义的messages.properties文件,其中包含以下值:

NotNull=This field is mandatory
BankHoliday=You cannot select a bank holiday

我对BankHoliday的注释如下:

@Documented
@Constraint(validatedBy = BankHolidayValidator.class)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BankHoliday {

    String message() default "{BankHoliday}";

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

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

我的验证器如下:

public class BankHolidayValidator implements ConstraintValidator<BankHoliday, Date> {

@Override
public void initialize(BankHoliday bankHoliday) { }

@Override
public boolean isValid(Date date, ConstraintValidatorContext cxt) {

    if(date == null) {
        cxt.disableDefaultConstraintViolation();
        cxt.buildConstraintViolationWithTemplate("{NotNull}").addConstraintViolation();
        return false;
    } else if (isBankHoliday(date)) {
        return false;
    } else {
        return true;
    }
}

}

我的模型使用@BankHoliday注释进行注释:

@BankHoliday
@DateTimeFormat(pattern = "dd/MM/yy")
private Date desiredBookingDate;

我的控制器如下:

@RequestMapping(value="/new/request", method = RequestMethod.POST)
public String putNewRequest(@Valid @ModelAttribute("request") Request request, BindingResult bindingResult, Map<String, Object> map) {

    if (bindingResult.hasErrors()) {

        // return them back

    } else {

        // process the request
    }
}

但是,当用户未填充此字段时,他们看到的错误消息是“您无法选择银行假日”而不是“此字段是必填字段”。逐步完成代码后,我可以看到cxt.disableDefaultConstraintViolation()行肯定被调用,并且正在添加{NotNull}约束验证,但用户始终会看到默认消息。

我尝试将“{NotNull}”替换为“测试消息”,但这也不起作用。任何人都可以指出我正确的方向,为什么这不起作用?

2 个答案:

答案 0 :(得分:1)

有点晚了......但是我会把答案发给别人..

显然它与默认消息常量的名称有关。

{BankHoliday} could be replaced with {bank.holiday} (or any other key) and it will work.

当然..也重命名属性文件中的消息密钥。它不喜欢具有确切名称作为接口本身的消息。

答案 1 :(得分:0)

我查看了自己的代码(这是有效的),只有一个区别是你没有调用addNode()方法,所以我建议调用它:

cxt.disableDefaultConstraintViolation();
cxt.buildConstraintViolationWithTemplate("{NotNull}")
   .addNode("desiredBookingDate")
   .addConstraintViolation();

但是,恕我直言,你的方向是错误的:验证者应该只对一种类型的验证负责。要将字段标记为必填字段,最好使用@NotNull注释。您可能会遇到另一个问题:空字符串将始终通过此类约束。要解决这个问题,在Spring中,您应该使用StringTrimmerEditoremptyAsNull = true参数,在验证之前将空字符串转换为null值。