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

szx*_*nyc 5 spring spring-mvc spring-boot spring-web

问题:

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

目标

我想重写defaultMessage@ javax.validation.constraints.NotNull全球在我的应用程序基于Spring输入验证码秒。

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

@Bean
public LocalValidatorFactoryBean validator(MessageSource messageSource) {
  LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
  bean.setValidationMessageSource(messageSource);
  return bean;
}
Run Code Online (Sandbox Code Playgroud)

下一个让我很惊讶。Spring Validation 有这个漂亮的DefaultMessageCodesResolver,它为看起来像这样的失败提供了出色的代码策略:

"code": "NotNull",
"codes": [
   "NotNull.user.firstName",
   "NotNull.firstName",
   "NotNull.java.lang.String",
   "NotNull"
],
Run Code Online (Sandbox Code Playgroud)

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

我在这里编写了一个示例应用程序,您可以看到它不起作用。

如何根据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?
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

其他一些相关的启动日志:

2018-03-26 14:32:22.970 TRACE 1093 --- [           main] o.s.beans.CachedIntrospectionResults     : Found bean property 'validationMessageSource' of type [org.springframework.context.MessageSource]
Run Code Online (Sandbox Code Playgroud)

验证约束:

public class User {
    @NotNull
    private String username;

    @NotNull
    private String firstName;
}
Run Code Online (Sandbox Code Playgroud)

仅用于测试的控制器:

@RestController
public class UserController {

    @PostMapping("/users")
    public List<ObjectError> testValidation(@Valid @RequestBody User user){
       return null; // null implies no failed validations.. just for testing
    }

}
Run Code Online (Sandbox Code Playgroud)

无法使用代码

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

Lê *_*Huy 1

因为配置的原因

@Bean
public LocalValidatorFactoryBean validator(MessageSource messageSource) {
    LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
    bean.setValidationMessageSource(messageSource);
    return bean;
}
Run Code Online (Sandbox Code Playgroud)

因此,您使用 Bean Validation,然后 spring 从 message.properties 文件获取消息,该文件使用 javax.validation.constraints.NotNull.message 键从 org.hibernate.validator.ValidationMessages.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
Run Code Online (Sandbox Code Playgroud)

要工作,你必须写如下:

@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; 
}
Run Code Online (Sandbox Code Playgroud)