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

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

     @RequestMapping(value = "/{id}")
@ResponseBody
public String getBook(@PathVariable("id") String id) {
Hello helloProxy = new HelloProxy();
helloProxy.say("Jack"); return id;
}

分析目录:

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

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

  3. 具体实现

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

    HandlerMethodReturnValueHandle用于处理返回值.

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

    

1. 接口定义

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

 package org.springframework.web.method.support;
public interface HandlerMethodArgumentResolver { /**
* 解析器是否支持参数
*/
boolean supportsParameter(MethodParameter parameter); /**
* 解析参数,填充到参数值
*/
Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception; }

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

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

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

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

看点代码:

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

 package org.springframework.web.method.support;
public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
private final List<HandlerMethodArgumentResolver> argumentResolvers =
new LinkedList<HandlerMethodArgumentResolver>();
public HandlerMethodArgumentResolverComposite addResolver(HandlerMethodArgumentResolver argumentResolver) {
this.argumentResolvers.add(argumentResolver);
return this;
} public HandlerMethodArgumentResolverComposite addResolvers(
List<? extends HandlerMethodArgumentResolver> argumentResolvers) {
if (argumentResolvers != null) {
for (HandlerMethodArgumentResolver resolver : argumentResolvers) {
this.argumentResolvers.add(resolver); // 难得没调addResolver
}
}
return this;
}

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

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

  先用parameter当key去缓存中取

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

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

 package org.springframework.web.method.support;
public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
public boolean supportsParameter(MethodParameter parameter) {
return getArgumentResolver(parameter) != null;
}
public Object resolveArgument(
MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
throws Exception { HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}
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;
}
}

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类型参数

SpringMVC源码解析 - HandlerAdapter - HandlerMethodArgumentResolver的更多相关文章

  1. SpringMVC源码解析- HandlerAdapter - ModelFactory(转)

    ModelFactory主要是两个职责: 1. 初始化model 2. 处理器执行后将modle中相应参数设置到SessionAttributes中 我们来看看具体的处理逻辑(直接充当分析目录): 1 ...

  2. SpringMVC源码解析- HandlerAdapter - ModelFactory

    ModelFactory主要是两个职责: 1. 初始化model 2. 处理器执行后将modle中相应参数设置到SessionAttributes中 我们来看看具体的处理逻辑(直接充当分析目录): 1 ...

  3. SpringMVC源码解析- HandlerAdapter初始化

    HandlerAdapter初始化时,主要是进行注解解析器初始化注册;返回值处理类初始化;全局注解@ControllerAdvice内容读取并缓存. 目录: 注解解析器初始化注册:@ModelAttr ...

  4. SpringMVC源码解析 - HandlerAdapter - @SessionAttributes注解处理

    使用SpringMVC开发时,可以使用@SessionAttributes注解缓存信息.这样业务开发时,就不需要一次次手动操作session保存,读数据. @Controller @RequestMa ...

  5. springMVC源码解析--ViewResolver视图解析器执行(三)

    之前两篇博客springMVC源码分析--ViewResolver视图解析器(一)和springMVC源码解析--ViewResolverComposite视图解析器集合(二)中我们已经简单介绍了一些 ...

  6. springMVC源码解析--HandlerMethodArgumentResolverComposite参数解析器集合(二)

    上一篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)中我们已经介绍了参数解析相关的东西,并且也提到了HandlerMethodArgume ...

  7. SpringMVC源码解析

    一:springmvc运行过程: 1. dispatcherServlet 通过 HandlerMapping 找到controller2. controller经过后台逻辑处理得到结果集modela ...

  8. 深入了解SpringMVC源码解析

    Spring MVC源码解析 Spring MVC的使用原理其实是通过配置一个Servlet来接管所有的请求,所有的请求由这个Servlet来进行分发处理. 我们可以从web.xml里面看出这一点 & ...

  9. springMVC源码解析--ViewResolverComposite视图解析器集合(二)

    上一篇博客springMVC源码分析--ViewResolver视图解析器(一)中我们介绍了一些springMVC提供的很多视图解析器ViewResolver,在开发的一套springMVC系统中是可 ...

随机推荐

  1. ccflow之相对路径

    最近在使用集成CCFlow系统时,在项目中直接运行可以,但发布到项目时老是报找不到文件的错误,后跟踪发现 BP.WF.Dev2Interface.UI_Window_OneWork(this.FK_F ...

  2. hdu 5909 Tree Cutting——点分治(树形DP转为序列DP)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治的话,每次要做一次树形DP:但时间应该是 siz*m2 的.可以用 FWT 变成 siz*ml ...

  3. SQL 相关分页方法

    [1] SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER OFFGO ALTER PROCEDURE [dbo].[procCom_Get_Pagination]( @ ...

  4. [C++ Primer] 第9章: 顺序容器

    顺序容器概述 顺序容器的类型有: 类型 说明 vector 可变长度数组. 支持快速随机访问. deque 双端队列. 支持快速随机访问. list 双向链表. 只支持双向顺序访问. forward_ ...

  5. Erlang Web 监控工具

    转自http://www.cnblogs.com/me-sa/archive/2012/04/17/erlang-web-monitor.html  Erlang已经提供了一系列工具查看运行时状态查看 ...

  6. NPOI-Excel系列-1000.创建一个标准的Excel文件

    using NPOI.HSSF.UserModel; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.IO; name ...

  7. bzoj4542 大数

    Description 小 B 有一个很大的数 S,长度达到了 N 位:这个数可以看成是一个串,它可能有前导 0,例如00009312345.小B还有一个素数P.现在,小 B 提出了 M 个询问,每个 ...

  8. php 数字格式化

    php 数字格式化 1.位数不足前面补0 <?php for($i=1; $i<=17 ;$i++){ $var = sprintf("0%3d",$i); echo ...

  9. 源文件封装为IP的步骤

    因为模块的交接,最好将写好的源文件和生成的IP封装一个IP,然后再转交给其他的同事使用,这是一种好的习惯.但是对于,封装的过程还是需要注意一下.实际的看看步骤吧.1)将源文件和使用到的IP生成工程. ...

  10. MySQL my.cnf参数配置优化详解

    [b]PS:本配置文件针对Dell R710,双至强E5620.16G内存的硬件配置.CentOS -100-300w的站点,主要使用InnoDB存储引擎.其他应用环境请根据实际情况来设置优化.[/b ...