使用自定义HandlerMethodArgumentResolver进行Spring MVC @Validvalidation

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

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

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

在上面的例子中,虽然我的解析器将被调用并且我的Domain参数将被初始化,但@Valid注释将不会被处理, 并且 BindingResult的解析器, ErrorsMethodArgumentResolver将失败,因为它需要BindingResultErrorsMethodArgumentResolver或者处理程序方法中的@RequestPart参数,我没有。

如果我尝试通过添加@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实例上拥有自定义创建行为。

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

很好地描述了您所面临的问题。

我检查了你已经概述的代码并得出了相同的结论 – 没有内置方法同时应用自定义HandlerMethodArgumentResolver以及@Valid相关validation,唯一的选择是执行ModelAttributeMethodProcessor所做的工作,检查参数是否具有@Valid注释并调用与validation逻辑相关的代码。

你可以从ModelAttributeMethodProcessor派生你的HandlerMethodResolverArgumentResolver并调用super.validateIfApplicable(..)至少以这种方式利用现有代码。

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

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