使用自定义HandlerMethodArgumentResolver进行Spring MVC @Valid验证

时间:2013-08-06 22:58:27

标签: java spring

我想注册一个可以处理以下HandlerMethodArgumentResolver处理程序方法定义的自定义@Controller

@RequestMapping(method = RequestMethod.POST)
public String createDomain(@Valid Domain domain, BindingResult errors, @RequestParam("countryId") Long countryId) {

我可以通过从Domain覆盖addArgumentResolver()来注册我的解析器,它只是通过请求参数创建WebMvcConfigurerAdapter对象。当Spring尝试解析Domain参数时,它会遍历其HandlerMethodArgumentResolver列表(有很多)并选择第一个supports()参数。

在上面的示例中,虽然我的解析器将被调用,我的Domain参数将被初始化,@Valid注释将不会被处理解析器BindingResultErrorsMethodArgumentResolver会失败,因为它在处理程序方法中需要@ModelAttribute@RequestBody@RequestPart参数,而我没有。< / p>

如果我尝试通过添加@ModelAttribute

来修复它
@RequestMapping(method = RequestMethod.POST)
public String createDomain(@Valid @ModelAttribute Domain domain, BindingResult errors, @RequestParam("countryId") Long countryId) {

首先使用HandlerMethodArgumentResolver检查ModelAttributeMethodProcessor实施supports(),然后在我的自定义解析器之前解析参数(使用@ModelAttribute@Valid)。 BindingResult不会失败,但我不会在Domain实例上拥有自定义创建行为。

我可以复制粘贴代码进行验证并添加到ModelAttributeMethodProcessor中的模型,但我希望有一种更简单的方法来解析我的参数并执行验证而无需向模型添加对象。有这样的方式吗?

2 个答案:

答案 0 :(得分:9)

您正面临的问题的良好描述。

我查看了您已概述的代码并得出了相同的结论 - 没有内置方法可以同时进行自定义HandlerMethodArgumentResolver以及@Valid相关验证同时应用,唯一的选择是执行ModelAttributeMethodProcessor所做的事情,以检查参数是否具有@Valid注释并调用与验证逻辑相关的代码。

您可以从HandlerMethodResolverArgumentResolver派生ModelAttributeMethodProcessor,并至少以这种方式调用super.validateIfApplicable(..)来充分利用现有代码。

答案 1 :(得分:5)

可能为时已晚,但您的HandlerMethodArgumentResolver获取WebDataBinderFactory个对象作为最后一个参数,然后,为了连接验证,只需将其添加到您的解析器实现中:

Object resolvedObject = // your logic 
if(parameter.hasParameterAnnotation(Valid.class){
            binderFactory.createBinder(webRequest,resolvedObject,"resolvedObjectLogicalName").validate ();
}