SpringMVC源碼分析(6)剖析DefaultAnnotationHandlerMapping

來源:互聯網
上載者:User

標籤:springmvc

接<SpringMVC源碼分析(5)剖析重要組件HandlerMapping>,繼續剖析HandlerMapping,DefaultAnnotationHandlerMapping是SpringMVC 中最重要的HandlerMapping組件。雖然它在spring3.1版本後被廢棄了。

包括2部分內容

  1. DefaultAnnotationHandlerMapping剖析

  2. HandlerMapping的攔截器

1.DefaultAnnotationHandlerMapping剖析

鑒於它的重要地位,貼下結構圖

650) this.width=650;" src="http://s1.51cto.com/wyfs02/M01/8B/03/wKioL1hCKnWx4gYCAACX0CQYtFA954.png" title="111.png" alt="wKioL1hCKnWx4gYCAACX0CQYtFA954.png" />

public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandlerMapping {    //是否使用尾碼註冊url(比如如果註冊了/users,同時也會註冊 /users.* 和/users/   private boolean useDefaultSuffixPattern = true;    //緩衝handler和requestMapping條件關係,驗證時使用   private final Map<Class, RequestMapping> cachedMappings = new HashMap<Class, RequestMapping>();      ...   }

1.1. 重寫determineUrlsForHandler方法

AbstractDetectingUrlHandlerMapping的子類,重寫determineUrlsForHandler方法;

initApplicationContext時被調用。為determineUrlsForHandler調用上下文。在springmvc容器初始化過程中調用。

650) this.width=650;" src="http://s4.51cto.com/wyfs02/M02/8B/03/wKioL1hCK1yhXCRbAABFzPcjfXs824.png" title="233.png" alt="wKioL1hCK1yhXCRbAABFzPcjfXs824.png" />

在上篇文章中總結過,HandlerMapping的主要職責

  1. 註冊Handler.可以是註解,可以是XML聲明。

  2. 產生url,有很多策略。beanName,首碼,包名稱都可以作為參考

  3. 維護mapping關係

  4. url的匹配能力

DefaultAnnotationHandlerMapping也是如此,determineUrlsForHandler方法,根據方法名就可以猜到,“為Handler匹配URL”。和ControllerClassNameHandlerMapping,ControllerBeanNameHandlerMapping之流是辦的事一樣的。區別就是他們是基於XML定義的,靈活性不足。DefaultAnnotationHandlerMapping靈活性和功能上更強大而已,名稱從RequestMapping註解中擷取。具體可以參考determineUrlsForHandlerMethods方法。

//按方法逐個產生URLprotected String[] determineUrlsForHandlerMethods(Class<?> handlerType, final boolean hasTypeLevelMapping) {   String[] subclassResult = determineUrlsForHandlerMethods(handlerType);   if (subclassResult != null) {      return subclassResult;   }   final Set<String> urls = new LinkedHashSet<String>();   Set<Class<?>> handlerTypes = new LinkedHashSet<Class<?>>();   handlerTypes.add(handlerType);   handlerTypes.addAll(Arrays.asList(handlerType.getInterfaces()));   for (Class<?> currentHandlerType : handlerTypes) {      ReflectionUtils.doWithMethods(currentHandlerType, new ReflectionUtils.MethodCallback() {         public void doWith(Method method) {            RequestMapping mapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);            if (mapping != null) {               String[] mappedPatterns = mapping.value();               if (mappedPatterns.length > 0) {                  for (String mappedPattern : mappedPatterns) {                     if (!hasTypeLevelMapping && !mappedPattern.startsWith("/")) {                        mappedPattern = "/" + mappedPattern;                     }                     addUrlsForPath(urls, mappedPattern);                  }               }               else if (hasTypeLevelMapping) {                  // empty method-level RequestMapping                  urls.add(null);               }            }         }      }, ReflectionUtils.USER_DECLARED_METHODS);   }   return StringUtils.toStringArray(urls);}

2.HandlerMapping的攔截器

2.1 Interceptor位置

從下面的結構圖中可以看出,攔截器分布在2個位置,分為2類。

MappedInterceptor是與url綁定的,對合格URL進行攔截;

Interceptor是屬於全域範圍的,對所有請求進行進行攔截。

650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/8B/07/wKiom1hCMDzyA3KAAAA1iMyumJU462.png" title="1.png" alt="wKiom1hCMDzyA3KAAAA1iMyumJU462.png" />


2.2 Interceptor的類結構

650) this.width=650;" src="http://s1.51cto.com/wyfs02/M01/8B/03/wKioL1hCMruCfElNAACC0tMAcZI252.png" title="2.png" alt="wKioL1hCMruCfElNAACC0tMAcZI252.png" />


UserRoleAuthorizationInterceptor 檢查目前使用者的授權
PathExposingHandlerInterceptor 暴露bestMatchingPattern
ConversionServiceExposingInterceptor
暴露 ConversionService
ThemeChangeInterceptor 支援主題切換
LocaleChangeInterceptor 支援切換語言
UriTemplateVariablesHandlerInterceptor 暴露請求變數
 WebContentInterceptor 檢查,準備請求和響應

值得關注的是WebRequestInterceptor。需要專門開闢一章研究。

2.3 預設intercepter配置

<mvc:interceptors>   <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />   <bean class="org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor"/>   <mvc:interceptor>      <mvc:mapping path="/account"/>         <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"></bean>   </mvc:interceptor></mvc:interceptors>

這是一段最普通的聲明

650) this.width=650;" src="http://s4.51cto.com/wyfs02/M00/8B/04/wKioL1hCT1-ByAozAAByb2_2KaM218.png" title="3222.png" alt="wKioL1hCT1-ByAozAAByb2_2KaM218.png" />

我有了個誤解:<mvc:interceptors>的子標籤<bean>聲明的攔截器會設定在interceptor中,結果不是如此。

ConversionServiceExposingInterceptor是在解析標籤時,預設註冊的。<SpringMVC源碼分析(1)標籤解析>文章中提到過。

2.4 沒事找事型的配置

瞭解了spring mvc的標籤解析過程,很容易配置一個自訂程度比較高的處理器類。確點就是很繁瑣

如下

這一段代碼雖然可以運行,但缺少類型轉換攔截器,需要配置。

<bean  class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">   <property name="interceptors">      <array>         <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />      </array>   </property>   <property name="mappedInterceptors">      <list>         <bean class="org.springframework.web.servlet.handler.MappedInterceptor">            <constructor-arg index="0">               <list>                  <value>/account</value>               </list>            </constructor-arg>            <constructor-arg index="1">               <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"></bean>            </constructor-arg>         </bean>      </list>   </property></bean>

如此聲明,一定要把    <mvc:annotation-driven />注釋掉,否則系統會存在兩個DefaultAnnotationHandlerMapping。


個人感覺這一段和上面的<mvc:interceptors>效果是一樣的。

區別

僅是LocaleChangeInterceptor這樣公用的攔截器設定在了interceptors屬性上,

而不是mappedInterceptors。

源碼解析,一定不要停留在設定表面,要洞察底層細節。

當然,是預設配置好,還是原生態的配置好,一個是簡介透明,一個自訂程度高,各取所需。



本文出自 “簡單” 部落格,請務必保留此出處http://dba10g.blog.51cto.com/764602/1879103

SpringMVC源碼分析(6)剖析DefaultAnnotationHandlerMapping

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.