How to: Spring get rid of @Validate for automatic Controller validation?

后端 未结 3 1695
自闭症患者
自闭症患者 2021-02-09 13:39

I know about @Valid annotation to instruct spring to validate for example a Controller argument according to JSR-303 in such this example:

@GetMappi         


        
3条回答
  •  情话喂你
    2021-02-09 14:05

    I have finally came across with a working solution which may be not the optimal from the point of view of Spring configuration (as I said I'm Spring beginner).

    The idea was to modify the argument resolvers (the ones that implement HandlerMethodArgumentResolver), replacing the argument resolver associated to arguments with a @RequestBody annotation. Creating an inherited class from the default one (which is RequestResponseBodyMethodProcessor) and overriding a method in the class hierarchy which efectively determines if perform a validation or not (based in the presence of @Valid, @Validated, @ValidXxxxxx annotations as the default behaviour), making to always validate with no further check.

    So here is the code (I'm using Java 8 BTW):

    Extend RequestResponseBodyMethodProcessor to define validation strategy (in this case, always validate):

    public class MyRequestResponseBodyMethodProcessor extends RequestResponseBodyMethodProcessor {
    
        public MyRequestResponseBodyMethodProcessor(List> converters) {
            super(converters);
        }
    
        @Override
        protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) {
            binder.validate();      // always validating @RequestMapping annotated parameters ;)
        }
    }
    

    Define a @Configuration class where to replace default argument resolver:

    @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 mangledResolvers = requestMappingHandlerAdapter.getArgumentResolvers().stream()
                .map(resolver -> resolver.getClass().equals(RequestResponseBodyMethodProcessor.class) ?
                    requestResponseBodyMethodProcessor: resolver)
                .collect(Collectors.toList());
    
            requestMappingHandlerAdapter.setArgumentResolvers(mangledResolvers);
        }
    
    }
    

    Finally configure Spring to deliver your customized Bean in your Application configuration class:

    @Configuration
    @PropertySource("classpath:api.properties")
    public class MyRestApiConfiguration {
    
        @Bean
        @Autowired
        RequestResponseBodyMethodProcessor requestResponseBodyMethodProcessor(List> converters) {
            return new MyRequestResponseBodyMethodProcessor(converters);
        }
    
    }
    

提交回复
热议问题