本文章主要介紹handlermethodargumentresolver在springmvc中的使用,介紹幾個handlermethodargumentresolver具體的使用情況,然後說明handlermethodargumentresolver的注冊來源以及如何自定義注冊。
首先具體看下請求映射到的handler的對應的映射函數的參數形式有哪些:
handlermethodargumentresolver接口隻有兩個方法:
<a href="http://my.oschina.net/pingpangkuangmo/blog/376343#">?</a>
1
2
3
4
5
<code>//判斷是否支援要轉換的參數類型</code>
<code>boolean</code> <code>supportsparameter(methodparameter parameter);</code>
<code>//當支援後進行相應的轉換</code>
<code>object resolveargument(methodparameter parameter, modelandviewcontainer mavcontainer,</code>
<code> </code><code>nativewebrequest webrequest, webdatabinderfactory binderfactory)</code><code>throws</code> <code>exception;</code>
handlermethodargumentresolver接口的抽象類:abstractmessageconvertermethodargumentresolver僅僅引入了httpmessageconverter,即轉換的工作有這些httpmessageconverter來完成具體的轉換和判斷由子類來實作。
如下:
6
7
8
9
<code>public</code> <code>abstract</code> <code>class</code> <code>abstractmessageconvertermethodargumentresolver</code><code>implements</code> <code>handlermethodargumentresolver {</code>
<code> </code><code>protected</code> <code>final</code> <code>log logger = logfactory.getlog(getclass());</code>
<code> </code><code>protected</code> <code>final</code> <code>list<httpmessageconverter<?>> messageconverters;</code>
<code> </code><code>protected</code> <code>final</code> <code>list<mediatype> allsupportedmediatypes;</code>
<code> </code><code>//略</code>
<code>}</code>
abstractmessageconvertermethodargumentresolver 的抽象子類abstractmessageconvertermethodprocessor僅僅是加入了對響應資料進行轉換的支援。
也就是abstractmessageconvertermethodprocessor的子類不僅可以用來轉換請求資料,也可以用來轉換響應資料。
abstractmessageconvertermethodprocessor的子類httpentitymethodprocessor,支援請求和響應的轉換,代碼如下:
<code>@override</code>
<code> </code><code>public</code> <code>boolean</code> <code>supportsparameter(methodparameter parameter) {</code>
<code> </code><code>return</code> <code>httpentity.</code><code>class</code><code>.equals(parameter.getparametertype());</code>
<code> </code><code>}</code>
<code> </code><code>@override</code>
<code> </code><code>public</code> <code>boolean</code> <code>supportsreturntype(methodparameter returntype) {</code>
<code> </code><code>return</code> <code>httpentity.</code><code>class</code><code>.isassignablefrom(returntype.getparametertype());</code>
使用場景如下:
10
11
<code>@requestmapping</code><code>(value=</code><code>"/test/http"</code><code>,method=requestmethod.post)</code>
<code> </code><code>@responsebody</code>
<code> </code><code>public</code> <code>map<string,object> testhttp(httpentity<string> httpentity)</code>
<code> </code><code>//略</code>
<code> </code><code>}</code>
<code>@requestmapping</code><code>(value=</code><code>"/test/httpentity"</code><code>,method=requestmethod.get)</code>
<code> </code><code>public</code> <code>httpentity<string> testhttpentity(){</code>
<code> </code><code>//略</code>
abstractmessageconvertermethodprocessor的子類requestresponsebodymethodprocessor:支援@requestbody和@responsebody,代碼如下:
12
13
<code> </code><code>//查找參數中是否含有@requestbody注解</code>
<code> </code><code>return</code> <code>parameter.hasparameterannotation(requestbody.</code><code>class</code><code>);</code>
<code>//查找參數中是否含有@requestbody注解或者controller類上是否含有@requestbody</code>
<code> </code><code>return</code> <code>((annotationutils.findannotation(returntype.getcontainingclass(), responsebody.</code><code>class</code><code>) !=</code><code>null</code><code>) ||</code>
<code> </code><code>(returntype.getmethodannotation(responsebody.</code><code>class</code><code>) !=</code><code>null</code><code>));</code>
<code>@requestmapping</code><code>(value=</code><code>"/test/requestbody"</code><code>,method=requestmethod.post)</code>
<code> </code><code>public</code> <code>map<string,object> testrequestbody(</code><code>@requestbody</code> <code>map<string,object> map1){</code>
<code> </code><code>map<string,object> map=</code><code>new</code> <code>hashmap<string,object>();</code>
<code> </code><code>map.put(</code><code>"name"</code><code>,</code><code>"lg"</code><code>);</code>
<code> </code><code>map.put(</code><code>"age"</code><code>,</code><code>23</code><code>);</code>
<code> </code><code>map.put(</code><code>"date"</code><code>,</code><code>new</code> <code>date());</code>
<code> </code><code>return</code> <code>map;</code>
httpentitymethodprocessor具體的解析參數的過程:
<code> </code><code>public</code> <code>object resolveargument(methodparameter parameter, modelandviewcontainer mavcontainer,</code>
<code> </code><code>nativewebrequest webrequest, webdatabinderfactory binderfactory)</code>
<code> </code><code>throws</code> <code>ioexception, httpmediatypenotsupportedexception {</code>
<code> </code><code>httpinputmessage inputmessage = createinputmessage(webrequest);</code>
<code> </code><code>type paramtype = gethttpentitytype(parameter);</code>
<code> </code><code>object body = readwithmessageconverters(webrequest, parameter, paramtype);</code>
<code> </code><code>return</code> <code>new</code> <code>httpentity<object>(body, inputmessage.getheaders());</code>
就是通過httpmessageconverter來進一步的判斷是否支援httpentity<t>中我們想要的t類型以及是否支援相應的content-type,如public map<string,object> testhttp(httpentity<string> httpentity) ,則會選擇stringhttpmessageconverter來進行轉換。具體的選擇過程如下:
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<code>protected</code> <code><t> object readwithmessageconverters(httpinputmessage inputmessage,</code>
<code> </code><code>methodparameter methodparam, type targettype)</code><code>throws</code> <code>ioexception, httpmediatypenotsupportedexception {</code>
<code> </code><code>mediatype contenttype;</code>
<code> </code><code>try</code> <code>{</code>
<code> </code><code>contenttype = inputmessage.getheaders().getcontenttype();</code>
<code> </code><code>catch</code> <code>(invalidmediatypeexception ex) {</code>
<code> </code><code>throw</code> <code>new</code> <code>httpmediatypenotsupportedexception(ex.getmessage());</code>
<code> </code><code>if</code> <code>(contenttype ==</code><code>null</code><code>) {</code>
<code> </code><code>contenttype = mediatype.application_octet_stream;</code>
<code> </code><code>class<?> contextclass = methodparam.getcontainingclass();</code>
<code> </code><code>for</code> <code>(httpmessageconverter<?> converter :</code><code>this</code><code>.messageconverters) {</code>
<code> </code><code>if</code> <code>(converter</code><code>instanceof</code> <code>generichttpmessageconverter) {</code>
<code> </code><code>generichttpmessageconverter<?> genericconverter = (generichttpmessageconverter<?>) converter;</code>
<code> </code><code>if</code> <code>(genericconverter.canread(targettype, contextclass, contenttype)) {</code>
<code> </code><code>if</code> <code>(logger.isdebugenabled()) {</code>
<code> </code><code>logger.debug(</code><code>"reading ["</code> <code>+ targettype +</code><code>"] as \""</code> <code>+</code>
<code> </code><code>contenttype +</code><code>"\" using ["</code> <code>+ converter +</code><code>"]"</code><code>);</code>
<code> </code><code>}</code>
<code> </code><code>return</code> <code>genericconverter.read(targettype, contextclass, inputmessage);</code>
<code> </code><code>}</code>
<code> </code><code>}</code>
<code> </code><code>class<t> targetclass = (class<t>)</code>
<code> </code><code>resolvabletype.formethodparameter(methodparam, targettype).resolve(object.</code><code>class</code><code>);</code>
<code> </code><code>if</code> <code>(converter.canread(targetclass, contenttype)) {</code>
<code> </code><code>if</code> <code>(logger.isdebugenabled()) {</code>
<code> </code><code>logger.debug(</code><code>"reading ["</code> <code>+ targetclass.getname() +</code><code>"] as \""</code> <code>+</code>
<code> </code><code>contenttype +</code><code>"\" using ["</code> <code>+ converter +</code><code>"]"</code><code>);</code>
<code> </code><code>return</code> <code>((httpmessageconverter<t>) converter).read(targetclass, inputmessage);</code>
<code> </code><code>throw</code> <code>new</code> <code>httpmediatypenotsupportedexception(contenttype,</code><code>this</code><code>.allsupportedmediatypes);</code>
同理requestresponsebodymethodprocessor也會使用相應的httpmessageconverter來進行轉換。如public map<string,object> testrequestbody(@requestbody map<string,object> map1)則會選擇mappingjackson2httpmessageconverter或者mappingjacksonhttpmessageconverter來完成轉換。
再看看另一類的handlermethodargumentresolver:
requestparammethodargumentresolver支援的類型有,一種是含@requestparam注解的參數,另一種就是簡單類型,如integer、string、date、uri, url,locale等:
源代碼如下:
<code>public</code> <code>boolean</code> <code>supportsparameter(methodparameter parameter) {</code>
<code> </code><code>class<?> paramtype = parameter.getparametertype();</code>
<code> </code><code>if</code> <code>(parameter.hasparameterannotation(requestparam.</code><code>class</code><code>)) {</code>
<code> </code><code>if</code> <code>(map.</code><code>class</code><code>.isassignablefrom(paramtype)) {</code>
<code> </code><code>string paramname = parameter.getparameterannotation(requestparam.</code><code>class</code><code>).value();</code>
<code> </code><code>return</code> <code>stringutils.hastext(paramname);</code>
<code> </code><code>else</code> <code>{</code>
<code> </code><code>return</code> <code>true</code><code>;</code>
<code> </code><code>else</code> <code>{</code>
<code> </code><code>if</code> <code>(parameter.hasparameterannotation(requestpart.</code><code>class</code><code>)) {</code>
<code> </code><code>return</code> <code>false</code><code>;</code>
<code> </code><code>else</code> <code>if</code> <code>(multipartfile.</code><code>class</code><code>.equals(paramtype) ||</code><code>"javax.servlet.http.part"</code><code>.equals(paramtype.getname())) {</code>
<code> </code><code>else</code> <code>if</code> <code>(</code><code>this</code><code>.usedefaultresolution) {</code>
<code> </code><code>return</code> <code>beanutils.issimpleproperty(paramtype);</code>
beanutils.issimpleproperty(paramtype)判斷是否是簡單類型的具體内容如下:
<code>/**</code>
<code> </code><code>* check if the given type represents a "simple" property:</code>
<code> </code><code>* a primitive, a string or other charsequence, a number, a date,</code>
<code> </code><code>* a uri, a url, a locale, a class, or a corresponding array.</code>
<code> </code><code>* <p>used to determine properties to check for a "simple" dependency-check.</code>
<code> </code><code>* @param clazz the type to check</code>
<code> </code><code>* @return whether the given type represents a "simple" property</code>
<code> </code><code>* @see org.springframework.beans.factory.support.rootbeandefinition#dependency_check_simple</code>
<code> </code><code>* @see org.springframework.beans.factory.support.abstractautowirecapablebeanfactory#checkdependencies</code>
<code> </code><code>*/</code>
<code> </code><code>public</code> <code>static</code> <code>boolean</code> <code>issimpleproperty(class<?> clazz) {</code>
<code> </code><code>assert.notnull(clazz,</code><code>"class must not be null"</code><code>);</code>
<code> </code><code>return</code> <code>issimplevaluetype(clazz) || (clazz.isarray() && issimplevaluetype(clazz.getcomponenttype()));</code>
<code>public</code> <code>static</code> <code>boolean</code> <code>issimplevaluetype(class<?> clazz) {</code>
<code> </code><code>return</code> <code>classutils.isprimitiveorwrapper(clazz) || clazz.isenum() ||</code>
<code> </code><code>charsequence.</code><code>class</code><code>.isassignablefrom(clazz) ||</code>
<code> </code><code>number.</code><code>class</code><code>.isassignablefrom(clazz) ||</code>
<code> </code><code>date.</code><code>class</code><code>.isassignablefrom(clazz) ||</code>
<code> </code><code>clazz.equals(uri.</code><code>class</code><code>) || clazz.equals(url.</code><code>class</code><code>) ||</code>
<code> </code><code>clazz.equals(locale.</code><code>class</code><code>) || clazz.equals(class.</code><code>class</code><code>);</code>
即當請求為 http://localhost:8080/test?name=abc時,處理函數若為test(string name),則對name的解析就是采用requestparammethodargumentresolver來解析的。
requestheadermethodargumentresolver:主要用來處理含有@requestheader注解的參數,但同時該參數又不是map類型。如下:
<code> </code><code>return</code> <code>parameter.hasparameterannotation(requestheader.</code><code>class</code><code>)</code>
<code> </code><code>&& !map.</code><code>class</code><code>.isassignablefrom(parameter.getparametertype());</code>
<code> </code><code>protected</code> <code>object resolvename(string name, methodparameter parameter, nativewebrequest request)</code><code>throws</code> <code>exception {</code>
<code> </code><code>string[] headervalues = request.getheadervalues(name);</code>
<code> </code><code>if</code> <code>(headervalues !=</code><code>null</code><code>) {</code>
<code> </code><code>return</code> <code>(headervalues.length ==</code><code>1</code> <code>? headervalues[</code><code>0</code><code>] : headervalues);</code>
<code> </code><code>return</code> <code>null</code><code>;</code>
源代碼已經說明的很明白了。
使用場景:
<code>@requestmapping</code><code>(value=</code><code>"/test/requestheader"</code><code>,method=requestmethod.get)</code>
<code> </code><code>public</code> <code>map<string,object> testrequestheader(</code><code>@requestheader</code> <code>string accept){</code>
若想擷取所有的header資訊:則使用另一個requestheadermapmethodargumentresolver,它則用來擷取所有的header資訊:
41
42
43
44
<code>public</code> <code>class</code> <code>requestheadermapmethodargumentresolver</code><code>implements</code> <code>handlermethodargumentresolver {</code>
<code>//這裡已經寫明白了,要求參數必須含有@requestheader注解,并且是map類型</code>
<code> </code><code>&& map.</code><code>class</code><code>.isassignablefrom(parameter.getparametertype());</code>
<code> </code><code>public</code> <code>object resolveargument(</code>
<code> </code><code>methodparameter parameter, modelandviewcontainer mavcontainer,</code>
<code> </code><code>throws</code> <code>exception {</code>
<code> </code><code>if</code> <code>(multivaluemap.</code><code>class</code><code>.isassignablefrom(paramtype)) {</code>
<code> </code><code>multivaluemap<string, string> result;</code>
<code> </code><code>if</code> <code>(httpheaders.</code><code>class</code><code>.isassignablefrom(paramtype)) {</code>
<code> </code><code>result =</code><code>new</code> <code>httpheaders();</code>
<code> </code><code>result =</code><code>new</code> <code>linkedmultivaluemap<string, string>();</code>
<code> </code><code>for</code> <code>(iterator<string> iterator = webrequest.getheadernames(); iterator.hasnext();) {</code>
<code> </code><code>string headername = iterator.next();</code>
<code> </code><code>for</code> <code>(string headervalue : webrequest.getheadervalues(headername)) {</code>
<code> </code><code>result.add(headername, headervalue);</code>
<code> </code><code>return</code> <code>result;</code>
<code> </code><code>map<string, string> result =</code><code>new</code> <code>linkedhashmap<string, string>();</code>
<code> </code><code>string headervalue = webrequest.getheader(headername);</code>
<code> </code><code>result.put(headername, headervalue);</code>
從上面的解析過程可以看出,參數類型可以是普通的map類型,也可以是multivaluemap或者進一步的httpheaders,他們與普通map類型的差別是他們對value值後者們是以list形式存放,前者是以string形式存放。
<code> </code><code>public</code> <code>map<string,object> testrequestheader(</code><code>@requestheader</code> <code>map<string,object> map1){</code>
<code>public</code> <code>map<string,object> testrequestheader(</code><code>@requestheader</code> <code>multivaluemap<string,object> map1){</code>
pathvariablemethodargumentresolver:主要針對含有@pathvariable的參數,代碼如下:
<code> </code><code>if</code> <code>(!parameter.hasparameterannotation(pathvariable.</code><code>class</code><code>)) {</code>
<code> </code><code>return</code> <code>false</code><code>;</code>
<code> </code><code>if</code> <code>(map.</code><code>class</code><code>.isassignablefrom(parameter.getparametertype())) {</code>
<code> </code><code>string paramname = parameter.getparameterannotation(pathvariable.</code><code>class</code><code>).value();</code>
<code> </code><code>return</code> <code>stringutils.hastext(paramname);</code>
<code> </code><code>return</code> <code>true</code><code>;</code>
<code> </code><code>@suppresswarnings</code><code>(</code><code>"unchecked"</code><code>)</code>
<code> </code><code>map<string, string> uritemplatevars =</code>
<code> </code><code>(map<string, string>) request.getattribute(</code>
<code> </code><code>handlermapping.uri_template_variables_attribute, requestattributes.scope_request);</code>
<code> </code><code>return</code> <code>(uritemplatevars !=</code><code>null</code><code>) ? uritemplatevars.get(name) :</code><code>null</code><code>;</code>
對于支援的類型也說明的很詳細。首先必須含有@pathvariable注解,其次如果是map類型,必須要指定@pathvariable的值,即這個
argumentresolver隻能擷取一個uri變量。要想擷取多個則要使用pathvariablemapmethodargumentresolver:
<code> </code><code>pathvariable annot = parameter.getparameterannotation(pathvariable.</code><code>class</code><code>);</code>
<code> </code><code>return</code> <code>((annot !=</code><code>null</code><code>) && (map.</code><code>class</code><code>.isassignablefrom(parameter.getparametertype()))</code>
<code> </code><code>&& (!stringutils.hastext(annot.value())));</code>
<code>public</code> <code>object resolveargument(methodparameter parameter, modelandviewcontainer mavcontainer,</code>
<code> </code><code>nativewebrequest webrequest, webdatabinderfactory binderfactory)</code><code>throws</code> <code>exception {</code>
<code> </code><code>@suppresswarnings</code><code>(</code><code>"unchecked"</code><code>)</code>
<code> </code><code>(map<string, string>) webrequest.getattribute(</code>
<code> </code><code>handlermapping.uri_template_variables_attribute, requestattributes.scope_request);</code>
<code> </code><code>if</code> <code>(!collectionutils.isempty(uritemplatevars)) {</code>
<code> </code><code>return</code> <code>new</code> <code>linkedhashmap<string, string>(uritemplatevars);</code>
<code> </code><code>return</code> <code>collections.emptymap();</code>
它要求必須含有@pathvariable注解,并且必須是map類型,并且@pathvariable注解的value沒有值。同時我們可以從pathvariablemapmethodargumentresolver和pathvariablemethodargumentresolver上面看出,他們的取值都是從request的屬性上進行擷取的webrequest.getattribute(
handlermapping.uri_template_variables_attribute, requestattributes.scope_request);也就是說,在解析完@requestmapping比對工作後,便将這些參數設定進request的屬性上,屬性名為handlermapping.uri_template_variables_attribute。其他的handlermethodargumentresolver可以自行研究,這裡不再說明。
至此,我們就要說明下handlermethodargumentresolver的注冊來源:
它的來源分為兩部分,一部分spring預設的handlermethodargumentresolver,另一部分就是我們自定義的handlermethodargumentresolver。
還是先看mvc:annotation-driven中配置自定義的handlermethodargumentresolver:
<code><mvc:annotation-driven ></code>
<code> </code><code><mvc:argument-resolvers></code>
<code> </code><code><bean</code><code>class</code><code>=</code><code>"xxx"</code><code>></bean></code>
<code> </code><code></mvc:argument-resolvers></code>
<code> </code><code></mvc:annotation-driven></code>
在mvc:argument-resolvers标簽下配置相應的自定義的handlermethodargumentresolver。
然後在mvc:annotation-driven的注解驅動類annotationdrivenbeandefinitionparser中會有這樣的代碼:
<code>managedlist<?> argumentresolvers = getargumentresolvers(element, parsercontext);</code>
<code>//略</code>
<code>if</code> <code>(argumentresolvers !=</code><code>null</code><code>) {</code>
<code> </code><code>handleradapterdef.getpropertyvalues().add(</code><code>"customargumentresolvers"</code><code>, argumentresolvers);</code>
其中getargumentresolvers就是擷取我們自定義的handlermethodargumentresolver
<code>private</code> <code>managedlist<?> getargumentresolvers(element element, parsercontext parsercontext) {</code>
<code> </code><code>element resolverselement = domutils.getchildelementbytagname(element,</code><code>"argument-resolvers"</code><code>);</code>
<code> </code><code>if</code> <code>(resolverselement !=</code><code>null</code><code>) {</code>
<code> </code><code>managedlist<beandefinitionholder> argumentresolvers = extractbeansubelements(resolverselement, parsercontext);</code>
<code> </code><code>return</code> <code>wrapwebargumentresolverbeandefs(argumentresolvers, parsercontext);</code>
<code> </code><code>return</code> <code>null</code><code>;</code>
從上面的代碼可以看出,擷取我們自定義的handlermethodargumentresolver然後把它設定進requestmappinghandleradapter的customargumentresolvers參數中,requestmappinghandleradapter有兩個與handlermethodargumentresolver有關的參數:
<code>private</code> <code>list<handlermethodargumentresolver> customargumentresolvers;</code>
<code>private</code> <code>handlermethodargumentresolvercomposite argumentresolvers;</code>
handlermethodargumentresolvercomposite 也僅僅是内部存放一個list<handlermethodargumentresolver>集合,同時本身又繼承handlermethodargumentresolver,是以它的實作都是靠内部的list<handlermethodargumentresolver>集合來實作的。
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<code>private</code> <code>final</code> <code>list<handlermethodargumentresolver> argumentresolvers =</code>
<code> </code><code>new</code> <code>linkedlist<handlermethodargumentresolver>();</code>
<code>//使用了适合高并發的concurrenthashmap來進行緩存</code>
<code> </code><code>private</code> <code>final</code> <code>map<methodparameter, handlermethodargumentresolver> argumentresolvercache =</code>
<code> </code><code>new</code> <code>concurrenthashmap<methodparameter, handlermethodargumentresolver>(</code><code>256</code><code>);</code>
<code> </code><code>/**</code>
<code> </code><code>* return a read-only list with the contained resolvers, or an empty list.</code>
<code> </code><code>public</code> <code>list<handlermethodargumentresolver> getresolvers() {</code>
<code> </code><code>return</code> <code>collections.unmodifiablelist(</code><code>this</code><code>.argumentresolvers);</code>
<code> </code><code>* whether the given {@linkplain methodparameter method parameter} is supported by any registered</code>
<code> </code><code>* {@link handlermethodargumentresolver}.</code>
<code> </code><code>return</code> <code>getargumentresolver(parameter) !=</code><code>null</code><code>;</code>
<code> </code><code>* iterate over registered {@link handlermethodargumentresolver}s and invoke the one that supports it.</code>
<code> </code><code>* @exception illegalstateexception if no suitable {@link handlermethodargumentresolver} is found.</code>
<code> </code><code>handlermethodargumentresolver resolver = getargumentresolver(parameter);</code>
<code> </code><code>assert.notnull(resolver,</code><code>"unknown parameter type ["</code> <code>+ parameter.getparametertype().getname() +</code><code>"]"</code><code>);</code>
<code> </code><code>return</code> <code>resolver.resolveargument(parameter, mavcontainer, webrequest, binderfactory);</code>
<code> </code><code>* find a registered {@link handlermethodargumentresolver} that supports the given method parameter.</code>
<code> </code><code>private</code> <code>handlermethodargumentresolver getargumentresolver(methodparameter parameter) {</code>
<code> </code><code>handlermethodargumentresolver result =</code><code>this</code><code>.argumentresolvercache.get(parameter);</code>
<code> </code><code>if</code> <code>(result ==</code><code>null</code><code>) {</code>
<code> </code><code>for</code> <code>(handlermethodargumentresolver methodargumentresolver :</code><code>this</code><code>.argumentresolvers) {</code>
<code> </code><code>if</code> <code>(logger.istraceenabled()) {</code>
<code> </code><code>logger.trace(</code><code>"testing if argument resolver ["</code> <code>+ methodargumentresolver +</code><code>"] supports ["</code> <code>+</code>
<code> </code><code>parameter.getgenericparametertype() +</code><code>"]"</code><code>);</code>
<code> </code><code>if</code> <code>(methodargumentresolver.supportsparameter(parameter)) {</code>
<code> </code><code>result = methodargumentresolver;</code>
<code> </code><code>this</code><code>.argumentresolvercache.put(parameter, result);</code>
<code> </code><code>break</code><code>;</code>
<code> </code><code>return</code> <code>result;</code>
在requestmappinghandleradapter完成參數設定後,會調用afterpropertiesset方法
<code> </code><code>public</code> <code>void</code> <code>afterpropertiesset() {</code>
<code> </code><code>if</code> <code>(</code><code>this</code><code>.argumentresolvers ==</code><code>null</code><code>) {</code>
<code> </code><code>list<handlermethodargumentresolver> resolvers = getdefaultargumentresolvers();</code>
<code> </code><code>this</code><code>.argumentresolvers =</code><code>new</code> <code>handlermethodargumentresolvercomposite().addresolvers(resolvers);</code>
<code> </code><code>if</code> <code>(</code><code>this</code><code>.initbinderargumentresolvers ==</code><code>null</code><code>) {</code>
<code> </code><code>list<handlermethodargumentresolver> resolvers = getdefaultinitbinderargumentresolvers();</code>
<code> </code><code>this</code><code>.initbinderargumentresolvers =</code><code>new</code> <code>handlermethodargumentresolvercomposite().addresolvers(resolvers);</code>
<code> </code><code>if</code> <code>(</code><code>this</code><code>.returnvaluehandlers ==</code><code>null</code><code>) {</code>
<code> </code><code>list<handlermethodreturnvaluehandler> handlers = getdefaultreturnvaluehandlers();</code>
<code> </code><code>this</code><code>.returnvaluehandlers =</code><code>new</code> <code>handlermethodreturnvaluehandlercomposite().addhandlers(handlers);</code>
<code> </code><code>initcontrolleradvicecache();</code>
getdefaultargumentresolvers方法完成了所有的handlermethodargumentresolver的彙總,如下:
<code>private</code> <code>list<handlermethodargumentresolver> getdefaultargumentresolvers() {</code>
<code> </code><code>list<handlermethodargumentresolver> resolvers =</code><code>new</code> <code>arraylist<handlermethodargumentresolver>();</code>
<code> </code><code>// annotation-based argument resolution</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>requestparammethodargumentresolver(getbeanfactory(),</code><code>false</code><code>));</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>requestparammapmethodargumentresolver());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>pathvariablemethodargumentresolver());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>pathvariablemapmethodargumentresolver());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>matrixvariablemethodargumentresolver());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>matrixvariablemapmethodargumentresolver());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>servletmodelattributemethodprocessor(</code><code>false</code><code>));</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>requestresponsebodymethodprocessor(getmessageconverters()));</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>requestpartmethodargumentresolver(getmessageconverters()));</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>requestheadermethodargumentresolver(getbeanfactory()));</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>requestheadermapmethodargumentresolver());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>servletcookievaluemethodargumentresolver(getbeanfactory()));</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>expressionvaluemethodargumentresolver(getbeanfactory()));</code>
<code> </code><code>// type-based argument resolution</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>servletrequestmethodargumentresolver());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>servletresponsemethodargumentresolver());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>httpentitymethodprocessor(getmessageconverters()));</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>redirectattributesmethodargumentresolver());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>modelmethodprocessor());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>mapmethodprocessor());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>errorsmethodargumentresolver());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>sessionstatusmethodargumentresolver());</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>uricomponentsbuildermethodargumentresolver());</code>
<code> </code><code>// custom arguments</code>
<code>//擷取我們自定義的handlermethodargumentresolver</code>
<code> </code><code>if</code> <code>(getcustomargumentresolvers() !=</code><code>null</code><code>) {</code>
<code> </code><code>resolvers.addall(getcustomargumentresolvers());</code>
<code> </code><code>// catch-all</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>requestparammethodargumentresolver(getbeanfactory(),</code><code>true</code><code>));</code>
<code> </code><code>resolvers.add(</code><code>new</code> <code>servletmodelattributemethodprocessor(</code><code>true</code><code>));</code>
<code> </code><code>return</code> <code>resolvers;</code>
不僅彙總了spring預設的,同時加進來我們自定義的handlermethodargumentresolver。至此,handlermethodargumentresolver的來龍去脈都說清楚了。然後就是我們自定義handlermethodargumentresolver,下一篇文章再說。