【问题标题】:Spring Boot validation message is not being resolvedSpring Boot 验证消息未解决
【发布时间】:2018-01-23 08:02:01
【问题描述】:

我无法解决我的验证消息。

我已经通过网络搜索和阅读了几个小时,我想将这个问题与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) {

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

【问题讨论】:

    标签: java spring spring-boot thymeleaf


    【解决方案1】:

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

    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,它将被覆盖并且没有效果。

    希望对你有帮助。

    【讨论】:

    • 我克隆了你的代码,它工作正常。当然可以。但是,如果我将相关部分复制到我的代码中(并对其进行调整),我会得到相同的结果......如果你愿意,你可以在这里看到我的完整代码:bitbucket.org/Korashen/theheroestavern(服务器将在 :80 上运行)
    • @Korashen 我检查了你的代码并更新了我的答案以涵盖使用WebMvcConfigurerAdapter 配置类的情况。
    • 只定义一个Validator bean(第二个)就足够了。
    • 在 Spring Boot 上运行良好。
    • 不完全是我想要的,但它成功了!使用带有 REST api 的 Spring Boot 2.1.5 测试
    【解决方案2】:

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

    【讨论】:

    • 当我使用带有 Thymeleaf 的 Spring Boot 2.1.3 进行测试时,浏览器的语言环境没有考虑到 ValidationMessages.properties 中的这些消息。请参阅 stackoverflow.com/a/55058274/40064 了解我是如何解决的。
    • 文件ValidationMessages.properties应该直接放在'resources'目录下,不要放在子目录下,否则不起作用
    • @want2learn,根据您的回复,它确实有效,但我认为如果我们需要实施 i18l,那么这不适用于您的方法。
    • 您也可以简单地按照 i18n 方式获取此属性。
    • 此解决方案完美运行,在验证器@Qualifier("defaultValidator") Validator validator 中进行了接线测试,并使用DataBinder 验证bean 并进行进一步处理。除了 ValidationMessages.properties 之外,我还添加了带有语言代码(如“en”)的 ValidationMessages_LC.properties 文件。
    【解决方案3】:

    我使用的是 Spring Boot 的 2.2.7 版本,只需将属性文件名更改为 ValidationMessages.properties 即可工作,无需其他配置。

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题,在阅读了这里的答案后,我发现文件名应该只是 'ValidationMessages.properties'。 我首先将它命名为其他名称,但它也不适用于我。直到我将其重命名为 ValidationMessages.properties

      【讨论】:

        【解决方案5】:

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

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

         - ValidationMessages_en.properties
         - ValidationMessages_de.properties
        

        然后,感谢 Spring 的魔法,你可以这样做:

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

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

        【讨论】:

          【解决方案6】:

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

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

          【讨论】:

            【解决方案7】:
            @Configuration
            public class LocalizationMessageSource {
            
                @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 class User{
              private @NotNull(message = "{serviceNumber.required}") String serviceNumber;
            
            }
            

            这种用法是错误的。

            public class User{
              private @NotNull(message="{serviceNumber.required}") String serviceNumber;  
            }
            

            【讨论】:

              【解决方案8】:

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

              【讨论】:

                猜你喜欢
                • 2021-07-17
                • 2020-02-04
                • 1970-01-01
                • 2017-12-28
                • 2022-01-09
                • 1970-01-01
                • 2017-09-15
                • 1970-01-01
                • 2020-09-27
                相关资源
                最近更新 更多