使用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}”替换为“测试消息”,但这也不起作用。任何人都可以指出我正确的方向,为什么这不起作用?
答案 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中,您应该使用StringTrimmerEditor
和emptyAsNull
= true
参数,在验证之前将空字符串转换为null
值。