[英]Custom Messages in Bean Validation using Spring’s Validator interface
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验证API和Spring的验证器接口,我尝试了两者,并且遇到了相同的问题),并且验证工作正常,但是我无法配置自定义消息。
I have configured a messages.properties file, and I can access the messages on this file just fine. 我已经配置了messages.properties文件,并且可以很好地访问此文件上的消息。 However this validation seems not to be capable of reading or accessing my messages source (messages.properties) configured automatically via spring boot.
但是,此验证似乎无法读取或访问通过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). 我可以直接通过@Autowired从控制器中注入的消息源对象访问消息(代码中有注释)。 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.
但是,Spring的验证器接口或JSR-303 Bean验证的绑定结果似乎无法访问MessageSource中加载的messages.properties。 The result I have is that my errors have codes but don't have default messages.
我得到的结果是我的错误有代码,但没有默认消息。
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. 因此,此代码可以正常工作,并且由于我使用无效的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 ? 有没有一种方法可以使我的Spring验证接口或JSR-303验证在Spring Boot中合并加载的message.properties(messagesource)? How can i correct this ?
我该如何纠正? If it's necessary i can paste my code sample of Spring Validation interfaces also.
如果有必要,我也可以粘贴Spring Validation接口的代码示例。
Thank's a lot, 非常感谢,
Tarcísio. 塔西奥(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());
}
} }
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 Boot since 1.5.3 you 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 before you 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 另请参阅文档
In Spring Boot applicaton MessageSource is configured with a MessageSourceAutoConfiguration and you don't need to autowire it. 在Spring Boot中,applicaton MessageSource配置了MessageSourceAutoConfiguration,您不需要对其自动布线。 For jsr303, create proper key-value pair in the messages.properties file.
对于jsr303,请在messages.properties文件中创建正确的键值对。 For "protocolo" field, you should have following values in property file.
对于“ 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());
}
}
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());
}
I solved this in custom message in Spring validation read the last part of my answer. 我在Spring验证中的自定义消息中解决了此问题,请阅读答案的最后一部分。
Check this example as 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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.