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類型參數

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM