精尽Spring MVC源码分析 - HandlerAdapter 组件(三)之 HandlerMethodArgumentResolver

该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读

Spring 版本:5.2.4.RELEASE

该系列其他文档请查看:《精尽 Spring MVC 源码分析 - 文章导读》

HandlerAdapter 组件

HandlerAdapter 组件,处理器的适配器。因为处理器 handler 的类型是 Object 类型,需要有一个调用者来实现 handler 是怎么被执行。Spring 中的处理器的实现多变,比如用户的处理器可以实现 Controller 接口或者 HttpRequestHandler 接口,也可以用 @RequestMapping 注解将方法作为一个处理器等,这就导致 Spring MVC 无法直接执行这个处理器。所以这里需要一个处理器适配器,由它去执行处理器

由于 HandlerMapping 组件涉及到的内容较多,考虑到内容的排版,所以将这部分内容拆分成了五个模块,依次进行分析:

《HandlerAdapter 组件(一)之 HandlerAdapter》

《HandlerAdapter 组件(二)之 ServletInvocableHandlerMethod》

《HandlerAdapter 组件(三)之 HandlerMethodArgumentResolver》

《HandlerAdapter 组件(四)之 HandlerMethodReturnValueHandler》

《HandlerAdapter 组件(五)之 HttpMessageConverter》

HandlerAdapter 组件(三)之 HandlerMethodArgumentResolver

本文是接着《HandlerAdapter 组件(二)之 ServletInvocableHandlerMethod》一文来分享 HandlerMethodArgumentResolver 组件。在 HandlerAdapter 执行处理器的过程中,具体的执行过程交由 ServletInvocableHandlerMethod 对象来完成,其中需要先通过 HandlerMethodArgumentResolver 参数解析器从请求中解析出方法的入参,然后再通过反射机制调用对应的方法。

回顾

先来回顾一下 ServletInvocableHandlerMethod 在哪里调用参数解析器的,可以回到 《HandlerAdapter 组件(二)之 ServletInvocableHandlerMethod》InvocableHandlerMethod 小节下面的 getMethodArgumentValues 方法,如下:

protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 获得方法的参数 MethodParameter[] parameters = getMethodParameters(); // 无参,返回空数组 if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; } // 将参数解析成对应的类型 Object[] args = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { // 获得当前遍历的 MethodParameter 对象,并设置 parameterNameDiscoverer 到其中 MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); // <1> 先从 providedArgs 中获得参数。如果获得到,则进入下一个参数的解析,默认情况 providedArgs 不会传参 args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] != null) { continue; } // <2> 判断 resolvers 是否支持当前的参数解析 if (!this.resolvers.supportsParameter(parameter)) { throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")); } try { // 执行解析,解析成功后,则进入下一个参数的解析 args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); } catch (Exception ex) { // Leave stack trace for later, exception may actually be resolved and handled... if (logger.isDebugEnabled()) { String exMsg = ex.getMessage(); if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) { logger.debug(formatArgumentError(parameter, exMsg)); } } throw ex; } } return args; }

<2> 处,在获取到 Method 方法的所有参数对象,依次处理,根据 resolvers 判断是否支持该参数的处理,如果支持则进行参数转换

resolvers 为 HandlerMethodArgumentResolverComposite 组合对象,包含了许多的参数解析器

HandlerMethodArgumentResolver 接口

org.springframework.web.method.support.HandlerMethodArgumentResolver,方法参数解析器

public interface HandlerMethodArgumentResolver { /** * 是否支持解析该参数 */ boolean supportsParameter(MethodParameter parameter); /** * 解析该参数 */ @Nullable Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception; } 类图

精尽Spring MVC源码分析 - HandlerAdapter 组件(三)之 HandlerMethodArgumentResolver

因为请求入参的场景非常多,所以 HandlerMethodArgumentResolver 的实现类也非常多,上面仅列出了部分实现类,本文也分析上面图中右侧常见的几种参数场景

HandlerMethodArgumentResolverComposite

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwgzpf.html