2017-04-18 49 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等。 –

相关问题