【问题标题】:Cannot override ConstraintValidator default message in Spring-MVC无法覆盖 Spring-MVC 中的 ConstraintValidator 默认消息
【发布时间】:2014-08-31 16:04:35
【问题描述】:

我在使用 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}”替换为“测试消息”,但这也不起作用。谁能指出我为什么这不起作用的正确方向?

【问题讨论】:

  • 您是否尝试过使用纯 Bean 验证的示例?基本上创建一个验证器实例并验证两个不同的实例,它们应该返回不同的消息。我基本上想知道问题是出现在 Bean Validation(又名 Hibernate Validator)还是在 Spring 集成中(也许消息被缓存了!?)。也就是说,我同意stackoverflow.com/a/25596487/115835 - 使用约束组合而不是动态更改消息更符合 Bean Validation 的精神 - goo.gl/pLg8Hi
  • 我已经研究了约束组合,这更合适,感谢指针。

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


【解决方案1】:

可能有点晚了..但我会为其他人发布我的答案..

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

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

当然……重命名属性文件中的消息键也是如此……它不喜欢与接口本身具有确切名称的消息。

【讨论】:

  • 它有效,但在 ValidationMessages.properties 中添加 {bank.holiday} 消息而不是 messages.properties
【解决方案2】:

我查看了我自己的代码(正在运行),唯一的区别是您没有调用 addNode() 方法,所以我建议调用它:

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

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

【讨论】:

  • 感谢您的回复。我尝试了cxt.buildConstraintViolationWithTemplate("{NotNull}").addNode("desiredBookingDate").addConstraintViolation();,但现在出现异常“JSR-303 验证的属性 'desiredBookingDate.desiredBookingDate' 没有对应的 Spring 数据绑定访问器”。此外,addNode() 现在已弃用,因此我尝试将其替换为addPropertyNode(),但失败并出现相同的错误。
  • 这是另一个错误,这意味着具有desiredBookingDate 属性的对象没有对应的setter (void setDesiredBookingDate(Date))。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-23
  • 2020-01-17
  • 2014-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-04
相关资源
最近更新 更多