2017-04-18 70 views
0

我有這個Web應用程序,我已經建立了bean驗證,它的工作非常好。但是對於一個字段,它不會讀取我在我的validation.properties文件中設置的消息。對於其他領域,它的作品。我感到困惑,爲什麼會發生這種情況?讓我告訴你我的設置:自定義驗證消息適用於某些錯誤

@Bean 
public MessageSource messageSource() { 
    ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); 
    messageSource.setCacheSeconds(0); 
    messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name()); 
    messageSource.setBasenames("/WEB-INF/Validation/validation"); //I have tried setBaseName as well but same difference. 
    return messageSource; 
} 

@Bean 
public LocalValidatorFactoryBean localValidatorFactoryBean() { 
    LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean(); 
    validator.setValidationMessageSource(this.messageSource()); 
    return validator; 
} 

@Bean 
public MethodValidationPostProcessor methodValidationPostProcessor() { 
    MethodValidationPostProcessor processor = new MethodValidationPostProcessor(); 
    processor.setValidator(this.localValidatorFactoryBean()); 
    return processor; 
} 

@Autowired 
SpringValidatorAdapter validator; //global validator 

@Override 
public Validator getValidator() { 
    return this.validator; 
} 

我的屬性文件位於正確的位置。我知道,因爲一些錯誤,消息從這個validation.properties文件中讀取。地點是:

的src \主\ web應用\ WEB-INF \確認\ validation.properties

裏面的內容是:

validate.user.yearsexperience =只有數字可以在這裏使用。

validate.user.phone =電話號碼只能是數字,應該是10位數字。

validate.user.name.blank =名稱不能留空或不能包含超過30個字符。它只會接受字母。也不允許使用數字或符號。

然後,我設置了以下錯誤代碼,預期bean驗證程序捕獲這些消息之一(但它沒有)。

typeMismatch.user.yearsexperience =在這裏只能使用數字。

typeMismatch.yearsexperience =此處只能使用數字。

typeMismatch.java.lang.Integer =這裏只能使用數字。

typeMismatch =此處只能使用數字。

所以,當我輸入錯誤數據phonename場,JSP顯示,我在validation.properties文件中設置這些消息,但對於yearsexperience領域,它表明了自己的typeMismatchcannot convert String to Integer, etc exceptions

下面就讓我來告訴你什麼註解我曾經在我的模型:

public class User{ 
    @NotBlankNoFancyLettersOrNumbers(message = "{validate.user.name.blank}") //My own custom annotation. Works like a charm and when user enters wrong data, it shows my custom error. 
    private String name; 
    @Pattern(regexp="(^$|[0-9]{10})", message = "{validate.user.phone}") //javax's builtin validation constraint 
    private String phone; 
    @So many things I have tried. But first I started with @Pattern 
    private Integer yearsexperience; 

對於這個Integer領域,我不能用@Pattern,因爲它只能放完了String場(我說的對嗎?)。

然後我試了@Digits。當用戶輸入錯誤的輸入時,它肯定會起作用,但不會顯示我的錯誤消息,它顯示用戶的例外typeMismatch。然後我做了自己的自定義註釋,並給它起了個名字@DigitsOnly。同樣的問題,它不會顯示我的錯誤消息。它顯示了與舊的typeMismatch例外情況相同的情況。

在這一點上,我想也許有一個表單綁定的問題(我應該不是認爲,因爲bean驗證適用於其他領域)。不管怎麼說,我註冊了自己的自定義編輯器,像這樣:

@InitBinder("user") 
protected void binder(WebDataBinder binder, HttpSession session) throws Exception {  
    binder.registerCustomEditor(Date.class, new DateConvertor()); //This is unrelated to my question but it works!  
    binder.registerCustomEditor(Integer.class, "yearsexperience", new IntegerConvertor(session.getAttribute("user"), this.userdao)); 
} 

這是我的類,它擴展PropertyEditorSupport

public class IntegerConvertor extends PropertyEditorSupport { 
private User user; 
private UserDAO userdao; 
public IntegerConvertor(){} 

public IntegerConvertor(Object object, UserDAO userdao) { 
    if (object instanceof User){    
     this.user= new User((User) object); 
    } 
    this.userdao = userdao; 
}  

@Override 
public void setAsText(String value) {  
if (!value.matches("[0-9]+")) { //if incoming value DOES NOT contains numbers only  
setValue(this.userdao.getYearsExperienceBeforeChange(this.user.getId())); 
} else {    
setValue(value); 
}  
} 

現在,我這樣做的,希望typeMismatch異常不會顯示給用戶,但是它仍然顯示出異常。 (我知道從這個PropertyEditorSupport,或者它不會從validation.properties文件讀取自定義的錯誤信息)。

無論如何,後來我嘗試添加自定義驗證通WebDataBinder.addValidator(myCustomValidator)這樣的:

@InitBinder("user") 
protected void binder(WebDataBinder binder, HttpSession session) throws Exception {  
    binder.registerCustomEditor(Date.class, new DateConvertor());  
    binder.addValidators(new myCustormValidator()); 
} 

這是我的自定義驗證的樣子,

public class MyCustormValidator implements Validator { 

@Override 
public boolean supports(Class<?> clazz) { 
    return User.class.equals(clazz); //return User.class.isAssignableFrom(clazz); 
} 
@Override 
public void validate(Object target, Errors errors) { 

    User user = (User) target; 
    String a = Integer.toString(user.getYearsExperience());  
    if(!a.matches("[0-9]+")){ 
     errors.rejectValue("yearsexperience","validate.user.yearsexperience"); 
    } 
    } 
} 

我轉換是IntegerString因爲那時我能夠檢查傳入值是否只包含數字而不包含字母。但在這裏會引起另一個問題:它不顯示傳入值,它顯示舊值。而且因爲舊的價值已經是正確的,它不會引起任何問題。所以我添加了其他聲明,只是爲了拋出一個錯誤,希望現在至少會顯示我的自定義錯誤。但它不!

因此,我來​​這裏尋求幫助。任何幫助是極大的讚賞。

TL; DR爲什麼自定義錯誤消息不顯示爲一個字段。但對於其他領域,它工作得很好。

+0

我建議你啓用DEBUG甚至TRACE級別,看看在日誌中會發生什麼。 –

+0

是的,謝謝你的建議。我會在今晚這樣做,然後我會告訴你,如果我找到任何東西。 –

+0

我試過了。我設置log4j2級別跟蹤,然後全部。只是在我輸入的價值被拒絕的任何地方都不會顯示。無處!除非我手動打印錯誤,否則沒有提及我的輸入'55b'。它沒有提到它被拒絕的地方。當我嘗試在myCustomValidator中打印值時,它只顯示前一個值而不是新值。 –

回答

1

爲什麼自定義錯誤顯示不出來的一些領域,但對其他人而言,工作完全正常

因爲有兩個不同的成分參與:

  • 的Hibernate驗證器正在用於bean驗證
  • spring-mvc綁定用戶值從a到a POJO類

您已經正確配置了用於bean驗證的消息源並且它可以工作。

但是你自定義typeMismatch消息,看起來像Spring MVC沒有看到這個。通常只需定義名稱爲messageSource的bean就足夠了,但出於某種奇怪的原因,在您的情況下您需要其他的東西。

我的猜測是你有2個上下文,messageSource是在上下文中定義的,它對Spring MVC不可見。


UPDATE: 我看着示例項目在GitHub上(http://github.com/farazdurrani/sscce),我看到與非工作不是配置的,因爲typeMismatch消息的問題。這是因爲您沒有使用標準標籤並嘗試手動顯示錯誤消息(通過從Errors.getAllErrors()的每個錯誤調用getDefaultMessage()方法)。如果您嘗試使用<form:errors path="*"/>,則會看到所有錯誤消息都已正確定位。

+0

Salava感謝您看看我的問題並回復。我只有一個應用程序上下文。這是根源環境。我知道這是因爲我的引導類正在擴展AbstractAnnotationConfigDispatcherServletInitializer。而且我重寫了getRootConfigClasses(),並且我只返回一個這樣的類:new Class [] {RootContextConfiguration.class} ;. –

+0

您是否嘗試將'basename'指定爲'WEB-INF/Validation/validation'(不帶前導斜槓)? –

+0

關於hibernate驗證器:我只使用java API(如java.beans.PropertyEditorSupport,javax.validation.ConstraintValidator或spring's api,如:org.springframework.validation.Validator等。 –

相關問題