简体   繁体   English

使用Spring的Validator界面进行Bean验证中的自定义消息

[英]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.

相关问题 使用Spring的Validator接口的Custom Bean Validator - Custom Bean Validator using Spring's Validator interface 使用Spring Validator进行自定义XSD模式验证 - custom xsd schema validation using spring validator 使用JSR-303和Spring的Validator的组合为Spring引导端点实现自定义验证逻辑 - Implementing custom validation logic for a spring boot endpoint using a combination of JSR-303 and Spring's Validator Spring bean验证消息解析 - Spring bean validation messages resolution 使用 Hibernate Validator 在 Spring Boot 中进行 Bean 验证失败时如何抛出自定义异常? - How to Throw a Custom Exception When Bean Validation In Spring Boot with Hibernate Validator Fails? 使用Struts 2 XML验证的自定义验证器错误消息 - Custom validator error messages with Struts 2 xml validation Hibernate自定义验证器消息Spring MVC - Hibernate Custom Validator Messages Spring MVC SpringBoot RESTful bean验证的自定义消息不起作用 - Custom messages for SpringBoot RESTful bean validation not working Spring 在控制器的处理程序方法中没有 @Valid 并且没有实现 Validator 接口的验证? - Spring Validation without @Valid in Controller's handler methods and without implementing Validator interface? 使用Hibernate Validator进行自定义验证 - Custom Validation Using Hibernate Validator
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM