如何:Spring摆脱@Validate进行自动控制器验证?

时间:2017-06-23 12:54:50

标签: spring spring-mvc spring-boot spring-aop spring-validator

我知道@Valid注释指示spring在这个例子中根据JSR-303验证例如一个Controller参数:

@GetMapping("/test")
public TestDTO testDTO(@Valid TestDTO testDTO){
        return testDTO;
}

但我希望能够以某种方式配置Spring以在所有控制器中启用验证,而无需明确指定@Valid注释。

这有可能吗?一些Spring配置?利用AOP?...

3 个答案:

答案 0 :(得分:3)

我终于找到了一个可行的解决方案,从Spring配置的角度来看可能不是最佳解决方案(正如我所说的那样,我是Spring初学者)。

我们的想法是修改参数解析器(实现HandlerMethodArgumentResolver的解析器),用@RequestBody注释替换与参数关联的参数解析器。从默认类(RequestResponseBodyMethodProcessor)创建一个继承的类,并覆盖类层次结构中的一个方法,该方法有效地确定是否执行验证(基于@Valid,{{1}的存在},@Validated注释作为默认行为),使得始终无需进一步检查即可验证。

所以这是代码(我使用Java 8 BTW):

扩展@ValidXxxxxx以定义验证策略(在这种情况下,始终验证):

RequestResponseBodyMethodProcessor

定义一个public class MyRequestResponseBodyMethodProcessor extends RequestResponseBodyMethodProcessor { public MyRequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters) { super(converters); } @Override protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) { binder.validate(); // always validating @RequestMapping annotated parameters ;) } } 类,用于替换默认参数解析器:

@Configuration

最后配置Spring以在您的Application配置类中提供自定义Bean:

@Configuration
public class MyValidationAdapterConfigurer {

    @Autowired
    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;

    // Injecting your own resolver
    @Autowired
    private RequestResponseBodyMethodProcessor requestResponseBodyMethodProcessor;


    @PostConstruct
    public void init() {

        // Don't know why but, removing the target resolver and adding the injected one to the end does not work!
        // Must be something related with the resolvers ordering. So just replacing the target in the same position.
        final List<HandlerMethodArgumentResolver> mangledResolvers = requestMappingHandlerAdapter.getArgumentResolvers().stream()
            .map(resolver -> resolver.getClass().equals(RequestResponseBodyMethodProcessor.class) ?
                requestResponseBodyMethodProcessor: resolver)
            .collect(Collectors.toList());

        requestMappingHandlerAdapter.setArgumentResolvers(mangledResolvers);
    }

}

答案 1 :(得分:1)

不幸的是,没有合法的&#34;这样做的方法。

此外@Valid还不够。您还需要BindingResult方法参数才能检查验证结果:bindingResult.hasErrors()

如果您不想使用BindingResult,您可以编写自己的Validator,并在输入无效的情况下抛出异常。

答案 2 :(得分:0)

应该可以这样做,但像Markus一样question我不确定我是否同意解决实际问题。

在没有深入杂草的情况下,Spring会在ModelAttributeMethodProcessor's validateIfApplicable方法中执行验证,作为模型绑定的一部分。根据javadoc

  

验证模型属性(如果适用)。默认实现   检查@ javax.validation.Valid,Spring的验证和自定义   名称以&#34开头的注释;有效&#34;。

要覆盖此功能,您需要创建自定义ModelAttributeMethodProcessor / ServletModelAttributeMethodProcessor。然后,您需要将其注册为参数解析器

public class ApplicationConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void addArgumentResolvers(final List<HandlerMethodArgumentResolver> argumentResolvers) {
        // add your custom model attribute processor here
    }
}