【问题标题】:Spring MVC @Valid Validation with custom HandlerMethodArgumentResolver带有自定义 HandlerMethodArgumentResolver 的 Spring MVC @Valid 验证
【发布时间】:2013-08-06 22:58:27
【问题描述】:

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

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

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

在上面的示例中,虽然我的解析器将被调用并且我的 Domain 参数将被初始化,但 @Valid 注释不会被处理并且BindingResult的解析器, ErrorsMethodArgumentResolver 将失败,因为它需要处理程序方法中的 @ModelAttribute@RequestBody@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 实例上拥有我的自定义创建行为。

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

【问题讨论】:

    标签: java spring


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 非常非常高效。谢谢。
      • 这应该是公认的答案,因为它可以完美地工作,而不必从 HandlerMethodResolverArgumentResolver 派生。
      • @Alexander 我试过这个,但它抛出了 java.lang.IllegalStateException 即“一个 Errors/BindingResult 参数应该紧跟在控制器方法签名中的模型属性参数之后”。跨度>
      • 验证有效,但我的控制器在验证错误后没有抛出异常。
      • 我必须这样做:``` WebDataBinder binder = binderFactory.createBinder(webRequest, resolvedObject, "resolvedObjectLogicalName"); binder.validate(); BindingResult bindingResult = binder.getBindingResult(); if (bindingResult.getErrorCount() > 0) { throw new MethodArgumentNotValidException(parameter, bindingResult); } ```
      猜你喜欢
      • 1970-01-01
      • 2013-08-27
      • 2014-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-18
      • 1970-01-01
      • 2016-02-13
      相关资源
      最近更新 更多