HandlerMethodArgumentResolver(三):基于HttpMessageConverter消息转换器的参数解析器【享学Spring MVC】(下)

简介: HandlerMethodArgumentResolver(三):基于HttpMessageConverter消息转换器的参数解析器【享学Spring MVC】(下)

Spring MVC参数处理器的注册与顺序


到这里,一个不落的把Spring MVC内置提供的参数处理器ArgumentResolver说了个遍。

前面我有提到过:参数处理对处理器的顺序是敏感的,因此我们需要关注Spring MVC最终的执行顺序,这时候我们的聚合容器HandlerMethodArgumentResolverComposite就出场了:

public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
  private final List<HandlerMethodArgumentResolver> argumentResolvers = new LinkedList<>();
  // 具有缓存
  private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache = new ConcurrentHashMap<>(256); 
  ...
  // @since 4.3  木有任何地方调用
  public void clear() {
    this.argumentResolvers.clear();
  }
  // getArgumentResolver()方法是本文的核心
  @Override
  public boolean supportsParameter(MethodParameter parameter) {
    return getArgumentResolver(parameter) != null;
  }
  @Override
  @Nullable
  public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
    // 这里是关键:每个参数最多只会被一个处理器处理
    HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
    if (resolver == null) {
      throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]." + " supportsParameter should be called first.");
    }
    return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
  }
  ... 
  // 这块逻辑保证了每个parameter参数最多只会被一个处理器处理
  // 这个从缓存的数据结构中也能够看出来的
  @Nullable
  private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
    HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
    if (result == null) {
      for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
        if (methodArgumentResolver.supportsParameter(parameter)) {
          result = methodArgumentResolver;
          this.argumentResolverCache.put(parameter, result);
          break;
        }
      }
    }
    return result;
  }
}


缺省情况Spring MVC注册的处理器(顺序)如下:

image.png

它初始化处的代码如下:


RequestMappingHandlerAdapter:
  @Override
  public void afterPropertiesSet() {
    ...
    // 26个,详见方法getDefaultArgumentResolvers
    if (this.argumentResolvers == null) {
      List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
      this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    // 12个  详见方法getDefaultInitBinderArgumentResolvers
    if (this.initBinderArgumentResolvers == null) {
      List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
      this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    ...
  }


注意:这里面initBinderArgumentResolvers最终只会有12个处理器,因为它的注册方法如下截图(也是这个顺序):


image.png


前面有提到过说标注有@InitBInder注解里也可以写很多类型的参数,但因为它只会有12个处理器,所以有些参数它是不能写的(比如@RequestBody、Errors等等这种都是不能写的),不用一一枚举,做到心中有数就成。


总结


本文介绍的处理内容,其实还是比较重要的,因为它和消息转换器HttpMessageConverter有关,毕竟它是我们目前主流的使用方式,希望可以帮助到大家理解。

这里可以提前预告一下:下篇文章将非常重要,因为我将结合实际场景,演示一个我们通过自定义HandlerMethodArgumentResolver实现的特殊场景的解决方案,非常的优雅和值得推广,有兴趣者可持续关注



相关文章
|
3月前
|
前端开发 Java 数据库连接
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
|
6月前
|
前端开发 IDE Java
Spring MVC 中因导入错误的 Model 类报错问题解析
在 Spring MVC 或 Spring Boot 开发中,若导入错误的 `Model` 类(如 `ch.qos.logback.core.model.Model`),会导致无法解析 `addAttribute` 方法的错误。正确类应为 `org.springframework.ui.Model`。此问题通常因 IDE 自动导入错误类引起。解决方法包括:删除错误导入、添加正确包路径、验证依赖及清理缓存。确保代码中正确使用 Spring 提供的 `Model` 接口以实现前后端数据传递。
172 0
|
10月前
|
JSON 自然语言处理 Java
OpenAI API深度解析:参数、Token、计费与多种调用方式
随着人工智能技术的飞速发展,OpenAI API已成为许多开发者和企业的得力助手。本文将深入探讨OpenAI API的参数、Token、计费方式,以及如何通过Rest API(以Postman为例)、Java API调用、工具调用等方式实现与OpenAI的交互,并特别关注调用具有视觉功能的GPT-4o使用本地图片的功能。此外,本文还将介绍JSON模式、可重现输出的seed机制、使用代码统计Token数量、开发控制台循环聊天,以及基于最大Token数量的消息列表限制和会话长度管理的控制台循环聊天。
3308 7
|
11月前
|
前端开发 Java UED
SpringMVC全局异常处理+拦截器使用+参数校验
通过使用 SpringMVC 的全局异常处理、拦截器和参数校验,可以有效提升 Web 应用程序的安全性、稳定性和用户体验。这些技术的合理应用,不仅可以保证代码的健壮性,还能提高代码的可维护性,为开发高质量的 Web 应用程序提供了坚实的基础。
263 6
|
11月前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
961 2
|
11月前
|
前端开发 Java Spring
探索Spring MVC:@Controller注解的全面解析
在Spring MVC框架中,`@Controller`注解是构建Web应用程序的基石之一。它不仅简化了控制器的定义,还提供了一种优雅的方式来处理HTTP请求。本文将全面解析`@Controller`注解,包括其定义、用法、以及在Spring MVC中的作用。
258 2
|
12月前
|
JSON 前端开发 Java
Spring MVC——获取参数和响应
本文介绍了如何在Spring框架中通过不同的注解和方法获取URL参数、上传文件、处理cookie和session、以及响应不同类型的数据。具体内容包括使用`@PathVariable`获取URL中的参数,使用`MultipartFile`上传文件,通过`HttpServletRequest`和`@CookieValue`获取cookie,通过`HttpSession`和`@SessionAttribute`获取session,以及如何返回静态页面、HTML代码片段、JSON数据,并设置HTTP状态码和响应头。
210 1
Spring MVC——获取参数和响应
|
11月前
|
前端开发 Java 开发者
Spring MVC中的控制器:@Controller注解全解析
在Spring MVC框架中,`@Controller`注解是构建Web应用程序控制层的核心。它不仅简化了控制器的定义,还提供了灵活的请求映射和处理机制。本文将深入探讨`@Controller`注解的用法、特点以及在实际开发中的应用。
701 0
|
12月前
|
前端开发 Java Spring
【Spring】“请求“ 之传递单个参数、传递多个参数和传递对象
【Spring】“请求“ 之传递单个参数、传递多个参数和传递对象
317 2
|
JSON API 数据格式
requests库中json参数与data参数使用方法的深入解析
选择 `data`或 `json`取决于你的具体需求,以及服务器端期望接收的数据格式。
797 2

推荐镜像

更多
  • DNS