SpringMVC源码解析 - HandlerAdapter - HandlerMethodArgumentResolver

HandlerMethodArgumentResolver主要负责执行handler前参数准备工作.

看个例子,红色部分的id初始化,填充值就是它干的活:

1     @RequestMapping(value = "/{id}")
2     @ResponseBody
3     public String getBook(@PathVariable("id") String id) {
4         Hello helloProxy = new HelloProxy();
5         helloProxy.say("Jack");
6         
7         return id;
8     }

 

分析目录:

  1. 接口定义(是否支持参数,处理参数)

  2. 代言人HandlerMethodArgumentResolverComposite,封装其他实现

  3. 具体实现

    composite除外,根据是否实现HandlerMethodReturnValueHandle分为XXXMethodArgumentResolver(不实现)和XXXMethodProssor(实现)

    HandlerMethodReturnValueHandle用于处理返回值.

    实现类实在太多,简单分析下各类的职责吧,具体内容看下面.

    

 

1. 接口定义

 老规矩,上来先看接口,看似很简单,一个是否支持,一个处理.

 1 package org.springframework.web.method.support;
 2 public interface HandlerMethodArgumentResolver {
 3 
 4     /**
 5      * 解析器是否支持参数
 6      */
 7     boolean supportsParameter(MethodParameter parameter);
 8 
 9     /**
10      * 解析参数,填充到参数值
11      */
12     Object resolveArgument(MethodParameter parameter,
13                            ModelAndViewContainer mavContainer,
14                            NativeWebRequest webRequest,
15                            WebDataBinderFactory binderFactory) throws Exception;
16 
17 }

 

2. 代言人HandlerMethodArgumentResolverComposite,封装其他实现

通过封装其他的实现,对外统一提供解析服务,这样用户在使用时,根本不用关心参数在哪里怎么解析处理的,只需要调用supportsParameter,resolveArgument就可以了.

而如果要扩充支持的类型也很简单,添加实现类,然后通过addResolver注册进来就可以了.

看到这个怎么想起设计模式的开闭原则了.对扩展开放,对修改关闭.

看点代码:

封装其他实现,并提供注册功能

 1 package org.springframework.web.method.support;
 2 public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
 3     private final List<HandlerMethodArgumentResolver> argumentResolvers =
 4             new LinkedList<HandlerMethodArgumentResolver>();
 5     public HandlerMethodArgumentResolverComposite addResolver(HandlerMethodArgumentResolver argumentResolver) {
 6         this.argumentResolvers.add(argumentResolver);
 7         return this;
 8     }
 9 
10     public HandlerMethodArgumentResolverComposite addResolvers(
11             List<? extends HandlerMethodArgumentResolver> argumentResolvers) {
12         if (argumentResolvers != null) {
13             for (HandlerMethodArgumentResolver resolver : argumentResolvers) {
14                 this.argumentResolvers.add(resolver); // 难得没调addResolver
15             }
16         }
17         return this;
18     }

在来看看具体是如何处理请求的:

都是都通过private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter)查找resolver实现的.

  先用parameter当key去缓存中取

  如果取不到迭代所有的reoslevers,一个个执行supportsParameter,直到有一个true.

  跟GOF的责任链设计模式定义一致.

 1 package org.springframework.web.method.support;
 2 public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
 3     public boolean supportsParameter(MethodParameter parameter) {
 4         return getArgumentResolver(parameter) != null;
 5     }
 6     public Object resolveArgument(
 7             MethodParameter parameter, ModelAndViewContainer mavContainer,
 8             NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
 9             throws Exception {
10 
11         HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
12         return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
13     }
14     private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
15         HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
16         if (result == null) {
17             for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
18                 if (methodArgumentResolver.supportsParameter(parameter)) {
19                     result = methodArgumentResolver;
20                     this.argumentResolverCache.put(parameter, result);
21                     break;
22                 }
23             }
24         }
25         return result;
26     }
27 }

 

3. 具体实现

实在太多了,先凑合看下各个类的职责吧,具体的分析后续在debug中做.

AbstractMessageConverterMethodArgumentResolver 使用HttpMessageConverter解析来自request body参数值的基类.

--AbstractMessageConverterMethodProcessor 添加返回值处理,所以改名了

----HttpEntityMethodProcessor 解析参数时,只处理HttpEntity;处理返回值时支持HttpEntity和ResponseEntity.

----RequestResponseBodyMethodProcessor 使用HttpMessageConverter解析@RequestBody参数;处理使用@ResponseBody的返回值

--RequestPartMethodArgumentResolver 解析使用@RequestPart,@RequestParam注解的参数;MultipartFile和Part的子类参数

AbstractNamedValueMethodArgumentResolver 解析named vlaue类型参数(其实就是键值对).

--AbstractCookieValueMethodArgumentResolver 解析使用@CookieValue注解的参数

----ServletCookieValueMethodArgumentResolver 从HttpServletRequest中解析出cookie值

--ExpressionValueMethodArgumentResolver 解析@Value注解的参数

--MatrixVariableMethodArgumentResolver 解析@MatrixVariable注解的参数,不包括map类型

--PathVariableMethodArgumentResolver 解析使用@PathVariable注解的参数,从uri中解析参数

--RequestHeaderMethodArgumentResolver 解析使用@RequestHeader注解的参数,不包括map类型

--RequestParamMethodArgumentResolver 解析从request流中获取值的参数,如@RequestParam,MultipartFile,Part,默认使用时解析基本参数.

AbstractWebArgumentResolverAdapter 使用@WebArgumentResolver的基类,用于向后兼容.适配WebArgumentResolver

--ServletWebArgumentResolverAdapter 新建NativeWebRequest--

ErrorsMethodArgumentResolver 处理Errors子类参数

MapMethodProcessor 处理map类型参数

MatrixVariableMapMethodArgumentResolver 使用@MatrixVariable注解的map类型参数

ModelAttributeMethodProcessor 解析使用@ModelAttribute注解参数

--ServletModelAttributeMethodProcessor 使用ServletRequestDataBinder解析参数

ModelMethodProcessor 处理model类型参数

PathVariableMapMethodArgumentResolver 处理使用@PathVariable注解的map参数

RedirectAttributesMethodArgumentResolver 处理RedirectAttributes类型参数

RequestHeaderMapMethodArgumentResolver 处理使用@RequestHeader注解的map参数

RequestParamMapMethodArgumentResolver 处理使用@RequestParam注解的map参数

ServletRequestMethodArgumentResolver 处理request相关的参数:WebRequest,ServletRequest,MultipartRequest,HttpSession,Principal,Locale,InputStream,Reader

ServletResponseMethodArgumentResolver 解析response相关的参数:ServletResponse,OutputStream,Writer

SessionStatusMethodArgumentResolver 处理SessionStatus类型参数

UriComponentsBuilderMethodArgumentResolver 处理UriComponentsBuilder类型参数

 

posted @ 2016-03-02 09:37  出门向左  阅读(3425)  评论(0编辑  收藏  举报