2014-08-31 63 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