2014-08-31 89 views
0

我在使用Spring验证时遇到覆盖默认ConstraintValidator消息的问题。无法重写Spring-MVC中的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}”,这也不起作用。任何人都可以指出我正确的方向,为什么这不起作用?

+1

您是否尝试过使用纯Bean验证的示例?基本上创建一个Validator实例并验证两个不同的实例,它们应该返回不同的消息。我基本上想知道这个问题是否发生在Bean Validation(又名Hibernate Validator)或Spring集成中(也许这些消息被缓存!)。这就是说,我同意http://stackoverflow.com/a/25596487/115835 - 它更多的是在Bean Validation的精神下使用约束组合来代替动态改变消息 - http://goo.gl/pLg8Hi – Hardy 2014-09-01 19:19:35

+0

我已经研究过约束组合,这比指针更适合。 – 2014-09-03 17:30:08

回答

0

我看着我自己的代码(这是工作)和唯一的区别是,你没有援引addNode()方法,所以我建议来调用它:

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

但是,恕我直言,你会走向错误的方向:验证者应仅对一种验证类型负责。要将字段标记为必填字段,最好使用@NotNull注释。你可能会面对另一个问题:空字符串总是会传递这样的约束。并且为了解决这个问题,在Spring中,您应该使用StringTrimmerEditoremptyAsNull = true参数,该参数在验证前将空字符串变为null值。

+0

Thanks for the reply.I try'cxt.buildConstraintViolationWithTemplate(“{NotNull}”)。addNode(“desiredBookingDate”)。addConstraintViolation();'但我现在得到一个异常“JSR-303验证属性'desiredBookingDate。desiredBookingDate'没有用于Spring数据绑定的相应访问器“。另外,'addNode()'现在已被弃用,所以我尝试了它的替换'addPropertyNode()',但失败的同一个错误。 – 2014-09-01 16:09:18

+0

这是另一个错误,它意味着具有desiredBookingDate属性的对象没有相应的setter('void setDesiredBookingDate(Date)')。 – 2014-09-01 18:37:38