java 使用 Spring 的 Validator 接口在 Bean Validation 中自定义消息
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39518562/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Custom Messages in Bean Validation using Spring’s Validator interface
提问by Tarcísio Filó
I'm using Spring Boot 1.3.5 with Rest Controllers and everything is working fine.
我正在将 Spring Boot 1.3.5 与 Rest Controllers 一起使用,并且一切正常。
I am also using Spring's validation sample techniques from the official documentation (JSR-303 Bean Validation API and Spring's validator interface, i tried both and faced the same problem) and the validations are working, but I am not able to configure custom messages.
我还使用了官方文档中的 Spring 验证示例技术(JSR-303 Bean Validation API 和 Spring 的验证器接口,我尝试了两者并遇到了同样的问题)并且验证工作正常,但我无法配置自定义消息。
I have configured a messages.properties file, and I can access the messages on this file just fine. However this validation seems not to be capable of reading or accessing my messages source (messages.properties) configured automatically via spring boot.
我已经配置了一个messages.properties 文件,我可以很好地访问这个文件中的消息。但是,此验证似乎无法读取或访问我通过 spring boot 自动配置的消息源 (messages.properties)。
I can access the messages directly from the messages source object injected in controller via @Autowired (there's a comment in the code). However, the binding result of the Spring's validator interface or the JSR-303 Bean Validation seems to not be capable of accessing the messages.properties loaded in MessageSource. The result I have is that my errors have codes but don't have default messages.
我可以直接从通过@Autowired 注入控制器的消息源对象访问消息(代码中有注释)。但是,Spring 的validator 接口或者JSR-303 Bean Validation 的绑定结果似乎无法访问MessageSource 中加载的messages.properties。我的结果是我的错误有代码但没有默认消息。
Here is my Application class:
这是我的应用程序类:
@SpringBootApplication
@ImportResource({ "classpath:security/cas-context.xml", "classpath:security/cas-integration.xml",
"classpath:security/security.xml" })
@EnableAutoConfiguration(exclude = VelocityAutoConfiguration.class) // http://stackoverflow.com/questions/32067759/spring-boot-starter-cache-velocity-is-missing
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public ServletRegistrationBean cxfServlet() {
return new ServletRegistrationBean(new CXFServlet(), "/services/*");
}
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
@Bean
public Nfse nfseService() {
return new NfseImpl();
}
@Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), nfseService());
endpoint.publish("/nfseSOAP");
return endpoint;
}
}
}
Here is my Bean:
这是我的豆子:
public class Protocolo {
private Long id;
@NotNull
@Min(1)
@Max(1)
private String protocolo;
private StatusProtocoloEnum status;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getProtocolo() {
return protocolo;
}
public void setProtocolo(String protocolo) {
this.protocolo = protocolo;
}
public StatusProtocoloEnum getStatus() {
return status;
}
public void setStatus(StatusProtocoloEnum status) {
this.status = status;
}
}
Here is My rest controller:
这是我的休息控制器:
@RestController
public class ProtocoloController {
@Autowired
private MessageSource messageSource;
@Autowired
private ProtocoloDAO protocoloDAO;
@RequestMapping(value = "/prot", method = RequestMethod.POST)
public void testar(@Valid @RequestBody Protocolo p) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
System.out.println(auth.getAuthorities());
System.out.println(messageSource.getMessage("protocolo.tamanho", null, null));
// IN THIS PART I'M ABLE TO PRINT THE MESSAGE IF VALIDATION IS DISABLED
System.out.println(p.getProtocolo());
}
}
}
So, this code works fine and the method is not called since i'm calling the method with a invalid Protocolo. However, my angularJS client receives the response with the errors codes populated but with all the default messages empty since the validation is not seeing my loaded messages.properties.
所以,这段代码工作正常并且没有调用该方法,因为我正在使用无效的协议调用该方法。但是,我的 angularJS 客户端收到响应,其中填充了错误代码,但所有默认消息都为空,因为验证没有看到我加载的 messages.properties。
Is there a way to make my Spring validation Interfaces or JSR-303 validation incorporate the loaded message.properties (messagesource) in spring boot ? How can i correct this ? If it's necessary i can paste my code sample of Spring Validation interfaces also.
有没有办法让我的 Spring 验证接口或 JSR-303 验证在 spring boot 中包含加载的 message.properties (messagesource) ?我该如何纠正?如果有必要,我也可以粘贴我的 Spring Validation 接口代码示例。
Thank's a lot,
非常感谢,
Tarcísio.
塔西西奥。
TEST CODE:
测试代码:
@RestController
public class ProtocoloController {
@Autowired
private MessageSource messageSource;
@Autowired
private ProtocoloDAO protocoloDAO;
@RequestMapping(value = "/prot", method = RequestMethod.POST)
public void testar(@Valid @RequestBody Protocolo p, BindingResult bindingResult) {
System.out.println(messageSource.getMessage("Min.protocolo.protocolo", null, null));
if (bindingResult.hasErrors()) {
System.out.println(bindingResult.getFieldError().getDefaultMessage());
System.out.println(bindingResult.getFieldError().getCode());
}
System.out.println(p.getProtocolo());
}
}
}
回答by Tobsch
Edit: Known Bug in Spring Boot 1.5.3 see https://github.com/spring-projects/spring-boot/issues/8979
编辑:Spring Boot 1.5.3 中的已知错误见https://github.com/spring-projects/spring-boot/issues/8979
In Spring Bootsince 1.5.3you need to do this
从1.5.3 开始在Spring Boot 中你需要这样做
@Configuration
public class ValidationMessageConfig {
@Bean
public LocalValidatorFactoryBean mvcValidator(MessageSource messageSource) {
LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean();
factory.setValidationMessageSource(messageSource);
return factory;
}
}
and then it will work.
然后它会起作用。
With version 1.5.2 and beforeyou can extend WebMVcConfigurerAdapter
使用1.5.2版并且可以扩展之前WebMVcConfigurerAdapter
@Configuration
public class ProfileMvcConfig extends WebMvcConfigurerAdapter {
private MessageSource messageSource;
@Autowired
public ProfileMvcConfig(MessageSource messageSource) {
this.messageSource = messageSource;
}
/**
* This method is overridden due to use the {@link MessageSource message source} in bean validation.
*
* @return A Validator using the {@link MessageSource message source} in bean validation.
*/
@Override
public Validator getValidator() {
LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean();
factory.setValidationMessageSource(messageSource);
return factory;
}
}
also see the documentation
另请参阅文档
回答by abaghel
In Spring Boot applicaton MessageSource is configured with a MessageSourceAutoConfiguration and you don't need to autowire it. For jsr303, create proper key-value pair in the messages.properties file. For "protocolo" field, you should have following values in property file.
在 Spring Boot 应用程序 MessageSource 中配置了 MessageSourceAutoConfiguration 并且您不需要自动装配它。对于 jsr303,在 messages.properties 文件中创建适当的键值对。对于“protocolo”字段,您应该在属性文件中具有以下值。
NotNull.protocolo.protocolo=Field cannot be left blank
Min.protocolo.protocolo=Minimum value must be {1}
You can also check messages from property file like below in your code.
您还可以在代码中检查来自属性文件的消息,如下所示。
public void testar(@Valid @RequestBody Protocolo p,BindingResult bindingResult) {
if(bindingResult.hasErrors()) {
System.out.println(bindingResult.getFieldError().getDefaultMessage());
}
}
回答by Lê v?n Huy
you should have following values in property file:
您应该在属性文件中具有以下值:
Min.protocolo.protocolo=Minimum value must be {1}
then in the controller you obtain the message by calling function getMessage from messageSource object
然后在控制器中,您通过从 messageSource 对象调用函数 getMessage 来获取消息
Test code:
测试代码:
@RequestMapping(value = "/prot", method = RequestMethod.POST)
public void testar(@Valid @RequestBody Protocolo p, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
bindingResult.getFieldErrors().forEach(fieldError ->
System.out.println(messageSource.getMessage(fieldError, Locale.getDefault()))
);
}
System.out.println(p.getProtocolo());
}
回答by Yan Khonski
I solved this in custom message in Spring validationread the last part of my answer.
我在 Spring 验证中的自定义消息中解决了这个问题,阅读了我答案的最后一部分。
Check this exampleas well.
也检查这个例子。
I used a custom validator with custom annotation. I needed to change code in my custom validator.
我使用了带有自定义注释的自定义验证器。我需要更改自定义验证器中的代码。
public class PersonValidator implements ConstraintValidator {
公共类 PersonValidator 实现 ConstraintValidator {
@Override
public boolean isValid(final Person person, final ConstraintValidatorContext context) {
if (somethingIsInvalid()) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("Something is invalid.").addConstraintViolation();
return false;
}
return true;
}
}