SpringMVC源码解析 - HandlerAdapter - HandlerMethodArgumentResolver
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的更多相关文章
- SpringMVC源码解析- HandlerAdapter - ModelFactory(转)
ModelFactory主要是两个职责: 1. 初始化model 2. 处理器执行后将modle中相应参数设置到SessionAttributes中 我们来看看具体的处理逻辑(直接充当分析目录): 1 ...
- SpringMVC源码解析- HandlerAdapter - ModelFactory
ModelFactory主要是两个职责: 1. 初始化model 2. 处理器执行后将modle中相应参数设置到SessionAttributes中 我们来看看具体的处理逻辑(直接充当分析目录): 1 ...
- SpringMVC源码解析- HandlerAdapter初始化
HandlerAdapter初始化时,主要是进行注解解析器初始化注册;返回值处理类初始化;全局注解@ControllerAdvice内容读取并缓存. 目录: 注解解析器初始化注册:@ModelAttr ...
- SpringMVC源码解析 - HandlerAdapter - @SessionAttributes注解处理
使用SpringMVC开发时,可以使用@SessionAttributes注解缓存信息.这样业务开发时,就不需要一次次手动操作session保存,读数据. @Controller @RequestMa ...
- springMVC源码解析--ViewResolver视图解析器执行(三)
之前两篇博客springMVC源码分析--ViewResolver视图解析器(一)和springMVC源码解析--ViewResolverComposite视图解析器集合(二)中我们已经简单介绍了一些 ...
- springMVC源码解析--HandlerMethodArgumentResolverComposite参数解析器集合(二)
上一篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)中我们已经介绍了参数解析相关的东西,并且也提到了HandlerMethodArgume ...
- SpringMVC源码解析
一:springmvc运行过程: 1. dispatcherServlet 通过 HandlerMapping 找到controller2. controller经过后台逻辑处理得到结果集modela ...
- 深入了解SpringMVC源码解析
Spring MVC源码解析 Spring MVC的使用原理其实是通过配置一个Servlet来接管所有的请求,所有的请求由这个Servlet来进行分发处理. 我们可以从web.xml里面看出这一点 & ...
- springMVC源码解析--ViewResolverComposite视图解析器集合(二)
上一篇博客springMVC源码分析--ViewResolver视图解析器(一)中我们介绍了一些springMVC提供的很多视图解析器ViewResolver,在开发的一套springMVC系统中是可 ...
随机推荐
- Docker中配置国内镜像
1. 为什么要为docker配置国内镜像 在正常情况下,docker有一个默认连接的国外官方镜像,在国外的网友访问该官方镜像自然不成问题,但是国内毕竟不是国外,由于国情不同,中国的网络访问国外官方 ...
- Renesas PPP Mode
不同厂家的NB/4G/2G,配置PPP模式略有差异,回调配置在如下路径: “synergy\ssp_supplemental\src\framework\sf_cellular_cat3\sf_cel ...
- 【整理总结】目录 - 代码沉淀 - 常见Nuget包介绍及使用
为了团队项目或者后期代码维护方便,现在项目已经极致推荐使用Nuget管理第三方类库了,所以下面列举的类库,都会在Nuget上获取到.目录排序不分先后,如果查找困难,请使用 ctrl + F 重要提示: ...
- [Android] 开发第七天
在另一台机器上安装 Android-Studio ,结果卡在了 Gradle 的下载界面上,网上各种方案都试了一遍,最终解决办法是: 然后新建了一个 App ,创建了新的签名并上传到手机上,安装时直接 ...
- [bat]批处理删默认共享和清理垃圾
@echo off net share c$ /del net share d$ /del net share e$ /del net share f$ /del net share g$ /del ...
- UDP协议发包的使用(DatagramSocket、DatagramPacket)
1.UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传 ...
- Mysql 授权远程访问
1.表示从任何主机连接到mysql服务器 GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' IDENTIFIED BY 'password' WITH GRANT O ...
- win10中打开SQL Server配置管理器方法
使用 Windows10 访问 SQL Server 配置管理器 因为 SQL Server 配置管理器是 Microsoft 管理控制台程序的一个管理单元而不是单独的程序,所以,当运行 Window ...
- 使用Fiddler实现网络限速
Fiddler实现网络限速方法: 1.点击FiddlerScript 2.在脚本里相应的地方添加“2”处两行代码(不加注释),保存(Save Script) 第一行为请求延时3秒,第二行为响应延时1. ...
- django-给外键关系传值,删除外键关系
反查: 在表关系里 related_name = '反查name',自己不设置,django也会默认设置为class的小写名字+_set , ex: book_set. 一对一关系赋值: class ...