我终于找到了一个可行的解决方案,从 Spring 配置的角度来看可能不是最佳解决方案(正如我所说的,我是 Spring 初学者)。
这个想法是修改参数解析器(实现 HandlerMethodArgumentResolver 的解析器),用 @RequestBody 注释替换与参数关联的参数解析器。从默认类(RequestResponseBodyMethodProcessor)创建一个继承类并覆盖类层次结构中的一个方法,该方法有效地确定是否执行验证(基于存在@Valid、@Validated、@ValidXxxxxx 注释作为默认行为),始终进行验证,无需进一步检查。
这里是代码(我使用的是 Java 8 BTW):
扩展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 类来替换默认参数解析器:
@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);
}
}
最后配置 Spring 以在您的 Application 配置类中交付您定制的 Bean:
@Configuration
@PropertySource("classpath:api.properties")
public class MyRestApiConfiguration {
@Bean
@Autowired
RequestResponseBodyMethodProcessor requestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters) {
return new MyRequestResponseBodyMethodProcessor(converters);
}
}