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