Spring Boot验证消息未解析

时间:2017-08-15 11:45:17

标签: java spring spring-boot thymeleaf

我无法解析验证消息。

我一直在网上搜索和阅读SO几个小时,我想将问题与Customize spring validation error

的明确答案联系起来

我确实定义了一个MessageSource bean,并且正确读取了 messages.properties ,因为我还使用它来显示th:text="#{some.prop.name}的常规文本,确实很好。 只是验证错误不会以它应该的方式工作。 我确定这是一个我忽略的愚蠢错误...... 验证本身工作正常。

约束:

@NotEmpty(message="{validation.mail.notEmpty}")
@Email()
private String mail;

messages.properties:

# Validation
validation.mail.notEmpty=The mail must not be empty!

模板部分:

<span th:if="${#fields.hasErrors('mail')}" th:errors="*{mail}"></span>

显示的文字:

{validation.mail.notEmpty}

我尝试了很多变化,都没有成功。

@NotEmpty(message="validation.mail.notEmpty")
@NotEmpty(message="#{validation.mail.notEmpty}")

只显示消息字符串的确切值,不解析。

<span th:if="${#fields.hasErrors('mail')}" th:errors="${mail}"></span>
<span th:if="${#fields.hasErrors('mail')}" th:errors="#{mail}"></span>
<span th:if="${#fields.hasErrors('mail')}" th:errors="#{*{mail}}"></span>
<span th:if="${#fields.hasErrors('mail')}" th:errors="#{__*{mail}__}"></span>

会导致错误。

编辑:

经过调试,我偶然发现了这个:

课程:org.springframework.context.support.MessageSourceSupport

方法:formatMessage(String msg, Object[] args, Locale locale)

将使用

调用

formatMessage("{validation.mail.notEmpty}", null, locale /*German Locale*/)

它会遇到if (messageFormat == INVALID_MESSAGE_FORMAT) {

所以...我的消息格式不正确。这超出了我的范围/知识。谁知道这意味着什么?

7 个答案:

答案 0 :(得分:36)

您的应用程序配置中似乎缺少LocalValidatorFactoryBean定义。您可以在下面找到定义两个bean的Application类的示例:使用LocalValidatorFactoryBean文件的MessageSourcemessages.properties

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@SpringBootApplication
public class Application {

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }

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

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

定义LocalValidatorFactoryBean bean后,您可以使用自定义验证消息,如:

@NotEmpty(message = "{validation.mail.notEmpty}")
@Email
private String email;

messages.properties

validation.mail.notEmpty=E-mail cannot be empty!

和Thymeleaf模板文件:

<p th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Name Error</p>

样本申请

  

https://github.com/wololock/stackoverflow-answers/tree/master/45692179

我准备了反映您问题的示例Spring Boot应用程序。随意克隆它并在本地运行它。如果使用表单发布的值不符合@NotEmpty@Email验证,它将显示已翻译的验证消息。

WebMvcConfigurerAdapter配置

如果要扩展WebMvcConfigurerAdapter,您必须通过从父类重写getValidator()方法来提供验证器,例如:

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }

    @Bean
    @Override
    public Validator getValidator() {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(messageSource());
        return bean;
    }

    // other methods...
}

否则,如果您在其他地方定义LocalValidatorFactoryBean bean,它将被覆盖并且不会产生任何影响。

我希望它有所帮助。

答案 1 :(得分:14)

不确定您使用的弹簧靴版本。我正在使用Spring boot 2.0.1.RELEASE。更清晰的解决方案是将所有验证消息移至ValidationMessages.properties。这样您就不必覆盖自动配置的Validator()并设置MessageSource

答案 2 :(得分:1)

我使用的是2.2.7发行版的Spring引导,后来我通过将属性文件名更改为ValidationMessages.properties并不需要其他配置来工作了。

答案 3 :(得分:1)

我遇到了同样的问题,在阅读了此处的答案后,我发现文件名应该仅为 'ValidationMessages.properties'。 我把它命名为不同的,直到将它重命名为 ValidationMessages.properties

答案 4 :(得分:1)

先生您好

关于“Wais Shuja”和“Ramesh Singh”的回答,我予以确认,因为我认为这是您正在寻找的正确解决方案。我扩展了他们的答案:

在文件夹 /resources/ 中,您可以创建与您支持的语言一样多的文件。在我的网络应用程序中,我使用德语和英语。因此,我创建了这两个文件:

 - ValidationMessages_en.properties
 - ValidationMessages_de.properties

然后,感谢 Spring 的魔法,你可以做到这一点:

@NotNull(message = "{error.mandatory}")
@Size(min = 1, message = "{error.mandatory}")
private String forname;

根据存储在 CookieLocaleResolver 中的语言选择合适的文件并插入文本。

亲切的问候
Oten Moten

答案 5 :(得分:0)

对于其余控制器,您将必须在方法参数的请求正文上添加@Valid批注。例如

@PostMapping
public User create(@Valid @RequestBody User user){
  //...
}

答案 6 :(得分:-2)

在解决这个问题后,我只是重新启动计算机,一切正常 我使用的是 Spring Boot 2.4.2 版