Spring Boot 将验证代码映射到 MessageSource 消息

标签 spring spring-mvc spring-boot spring-web

问题:

我正在尝试使用尽可能多的 Spring Boot Auto-configuration 来减少样板代码。我无法让 Spring 验证代码自动映射到我的外部化 messages.properties。只有当我添加我自己的 时它才会起作用LocalValidatorFactoryBean 并使用完全限定的 javax 约束消息。

目标

我想覆盖 defaultMessage @javax.validation.constraints.NotNull 全局在我的应用程序中 基于 Spring 验证码 s。

我做的第一件事就是注册这个 bean...我真的必须注册吗?我看到 Spring Boot 有一个,但它似乎与 messages.properties 无关。

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

下一个让我很惊讶。 Spring Validation 有这个漂亮的 DefaultMessageCodesResolver它为看起来像这样的失败提供了出色的代码策略:
"code": "NotNull",
"codes": [
   "NotNull.user.firstName",
   "NotNull.firstName",
   "NotNull.java.lang.String",
   "NotNull"
],

但是这些代码甚至不考虑用于@NotNull 约束。 Validation Conversion 的 spring 文档暗示这样的东西确实存在,但还没有任何有用的东西。

I wrote a sample application here and you can see that it's not working.

问题

如何根据messages.properties 中的代码覆盖Spring Validation 错误的默认消息?

相关 build.gradle
  • springBootVersion = '2.0.0.RELEASE'
  • 编译('org.springframework.boot:spring-boot-starter-web')

  • src/main/resources/messages.properties:
    NotNull.user.firstName=This doesn't work
    NotNull.firstName=Or this
    NotNull.java.lang.String=This doesn't work either
    NotNull=And this doesn't work
    
    javax.validation.constraints.NotNull.message=THIS DOES WORK! But why have codes then?
    

    Spring 自动配置输出证明已加载自动配置。
       MessageSourceAutoConfiguration matched:
          - ResourceBundle found bundle URL [file:/home/szgaljic/git/jg-github/journey-through-spring/basic-web-validations/build/resources/main/messages.properties] (MessageSourceAutoConfiguration.ResourceBundleCondition)
          - @ConditionalOnMissingBean (types: org.springframework.context.MessageSource; SearchStrategy: current) did not find any beans (OnBeanCondition)
    

    其他一些相关的启动日志:
    2018-03-26 14:32:22.970 TRACE 1093 --- [           main] o.s.beans.CachedIntrospectionResults     : Found bean property 'validationMessageSource' of type [org.springframework.context.MessageSource]
    

    验证约束:
    public class User {
        @NotNull
        private String username;
    
        @NotNull
        private String firstName;
    }
    

    仅用于测试的 Controller :
    @RestController
    public class UserController {
    
        @PostMapping("/users")
        public List<ObjectError> testValidation(@Valid @RequestBody User user){
           return null; // null implies no failed validations.. just for testing
        }
    
    }
    

    无法使用代码

    我试图评论/取消评论 messages.properties 中的消息,但它只会采用 的值javax.validation.constraints.NotNull.message .

    最佳答案

    因为配置

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

    因此,您正在使用 Bean 验证,然后使用键 javax.validation.constraints.NotNull.message 从 org.hibernate.validator.ValidationMessages.properties 文件覆盖的 message.properties 文件中获取消息。如果您想拥有键值对:
    NotNull.user.firstName=This doesn't work
    NotNull.firstName=Or this
    NotNull.java.lang.String=This doesn't work either
    NotNull=And this doesn't work
    

    工作你必须写如下:
    @Autowired
    private MessageSource messageSource;
    
    @PostMapping("/users")
    public List<ObjectError> testValidation(@Valid @RequestBody User user, BindingResult bindingResult){
       bindingResult.getFieldErrors().forEach(fieldError -> new ObjectError(
       /*Assumes that ObjectError has constructor of ObjectError(String message) */
              messageSource.getMessage(fieldError, Locale.getDefault())
       ));
       return null; 
    }
    

    关于Spring Boot 将验证代码映射到 MessageSource 消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49499891/

    相关文章:

    spring - 如何使用 Spring MVC 3.1 获取引用 URL

    tomcat错误部署 war

    java - lambda 中的控制反转

    spring - Spring Boot 1.5.x 与 Hibernate 4.x 的兼容性

    java - 如果等于 mustache 的条件

    java - 使用 Spring、Tomcat 和 Java,如何使用 HTTP header 重定向请求?

    spring-boot - 具有 Azure AD 安全性和 CORS 的 Spring Boot 3.0 不起作用,但在 Spring Boot 2.6 中起作用

    spring-boot - 我可以在 spring-data-rest 存储库中专门禁用 PATCH 吗?

    java - Spring:添加查询参数的惯用方式

    java - 用于 Web 应用程序的 Spring OAuth 库