我想注册一个可以处理以下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
注释将不会被处理和解析器BindingResult
,ErrorsMethodArgumentResolver
会失败,因为它在处理程序方法中需要@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
中的模型,但我希望有一种更简单的方法来解析我的参数并执行验证而无需向模型添加对象。有这样的方式吗?
答案 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 ();
}