欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringMVC中的handlerMappings對象用法

 更新時間:2021年09月26日 14:31:56   作者:喜歡火影的木易楊  
這篇文章主要介紹了SpringMVC中的handlerMappings對象用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

從SpringMVC源碼解析所用的例子,一個http://localhost:9090/web/hi?name=yang請求調(diào)用到下面的地方,發(fā)現(xiàn)一個特殊的對象handlerMappings,通過請求uri去找handler的時候需要通過這個handlerMapping來找,那么handlerMappings是怎么樣的呢?

從斷點調(diào)試中,我們可以看到這handlerMappings一共有5個,分別是WebMvcConfigurationSupportXXX,RequestMappingHandlerMapping和BeanNameUrlHandlerMapping。

首先,我們先了解一下這個handlerMappings是什么?從官方描述看,handlerMappings是DispatcherServlet內(nèi)部的一種Bean類型,DispatcherServlet內(nèi)部有很多Bean類型,包括HandlerMapping,HandlerAdapter,HandlerExceptionResolver,ViewResolver,LocaleResolver ,ThemesResolver,Multipart Resolver和FlashMapManager 。

其中HandlerMapping是一個將請求與用于預(yù)處理和后處理的攔截器列表一起映射起來的處理程序,除了WebMvcConfigurationSupportXXX供用戶自定義的映射處理器之外,

主要有以下兩種內(nèi)置類型:

(1)RequestMappingHandlerMapping(它支持@RequestMapping修飾的方法)

(2)SimpleUrlHandlerMapping(它為處理程序維護(hù)URI路徑模式的顯式注冊)

一.handlerMappings集合內(nèi)部的元素是什么,有什么作用?

通過官方文檔描述,handlerMappings集合內(nèi)部最主要有兩種映射處理器類型RequestMappingHandlerMapping和SimpleUrlHandlerMapping,它們分別用于處理不同類型的Controller。

我們知道可以通過注解@Controller或@RestController注解方式來聲明一個Controller,然后使用@RequestMapping來修飾類名或方法名,這種方式其實是由RequestMappingHandlerMapping映射處理器來對請求地址和方法名進(jìn)行映射的;那么SimpleUrlHandlerMapping又用于處理哪種方式的Controller呢,那就是采用實現(xiàn)Controller接口或?qū)崿F(xiàn)HttpRequestHandler接口的類,這種聲明Controller的方式是早期的做法現(xiàn)在在實際開發(fā)中用的比較少了但是也是SpringMVC所支持的。

對于RequestMappingHandlerMapping

這種類型的handlerMapping是我們通過@RequestMapping+請求地址來修飾方法時,會由這么一個映射器來對這種配置方式進(jìn)行解析和映射處理,也就是說RequestMappingHandlerMapping類型的映射器是為注解聲明方式的映射專門設(shè)計的,<K,V>映射關(guān)系會存儲在這個handlerMapping的Map中。

對于SimpleUrlHandlerMapping

這個映射器則是為繼承Controller類或?qū)崿F(xiàn)HttpRequestHandler接口的類進(jìn)行解析和映射處理的。

用代碼舉例子來驗證,我們分別新建兩個類分別實現(xiàn)Controller接口和實現(xiàn)HttpRequestHandler接口,在類中寫請求接收方法,那么通過這兩種聲明的Controller通過請求地址在查詢請求方法時就會由SimpleUrlHandlerMapping進(jìn)行存儲和映射,<K,V>映射關(guān)系會存儲在這個SimpleUrlHandlerMapping的Map中。

(1)實現(xiàn)Controller接口的方式:

(2)實現(xiàn)HttpRequestHandler接口的方式:

然后重新進(jìn)行debug,使用http://localhost:9090/beanweb或http://localhost:9090/beanweb2請求,就會看到在handlerMapping中查找handler時會跳過第一種注解類型的RequestMappingHandlerMapping,而真正進(jìn)行解析處理的就是第二種非注解方式SimpleUrlHandlerMapping:

因此我們現(xiàn)在就明白了這個handlerMappings映射處理器集合的數(shù)據(jù)是怎么樣的,集合內(nèi)存儲的映射處理器分別處理怎么樣的請求。那么這個集合數(shù)據(jù)是怎么初始化的呢?

二.handlerMappings集合是怎么初始化的?

通過IDEAJ的Find Usages工具,在本文圖一的this.handlerMappings進(jìn)行調(diào)用搜索,可以一層層找到如下調(diào)用鏈:

HttpServletBean.init-->initServletBean()-->FrameworkServlet.initServletBean-->
FrameworkServlet.initWebApplicationContext-->FrameworkServlet.onRefresh
-->DispatcherServlet.onRefresh-->DispatcherServlet.initStrategies-->DispatcherServlet.initHandlerMappings
-->DispatcherServlet.getDefaultStrategies-->strategies.add((T) strategy)

通過前面SpringMVC前兩個流程的學(xué)習(xí)可知,DispatcherServlet繼承了FrameworkServlet,同時就集成了HttpServlet,也就是說DispatcherServlet本質(zhì)上就是一個Servlet,那么在容器加載這個Servlet的時候如果設(shè)置了<load-on-startup>加載時馬上進(jìn)行初始化,則在加載時會自動執(zhí)行其init方法,于是就有了上面調(diào)用鏈的第一個HttpServletBean.init入口。

我們的目的是找到哪里進(jìn)行了handlerMappings的核心操作,通過調(diào)用關(guān)系我們找到核心代碼在DispatcherServlet.initHandlerMappings:

通過上面代碼返回的對象我們可以大膽推測matchingBeans就是我們要了解的handlerMappings集合,這個方法內(nèi)部完成了對多種類型HandlerMapping的初始化。通過查看我們重點關(guān)注的兩種映射器對象值,可以分別看到<K,V>關(guān)系:

上面就可以看到前面我們提到的urlLookup的Map集合以及handlerMap集合。為了了解這些不同的請求地址是怎么分配給不同類型的映射器來處理的,我們繼續(xù)點開這個核心方法:

實際由下面這行代碼完成了:

lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit)

而真正值得思考的邏輯在于

String[] beanNames = getBeanNamesForType(type, includeNonSingletons, allowEagerInit);

上面方法的邏輯就會自動生成一個有5種類型handlerMapping的handlerMappings,那么這5種映射器是怎么產(chǎn)生的呢?

通過核心代碼我們可以知道,這里通過傳入一個type="HandlerMapping"的類型,在beanDefinitionNames的集合中匹配所有屬于HandlerMapping類型的BeanName,然后放入到result數(shù)組返回,然后在單例池中根據(jù)BeanName獲取對應(yīng)的HandlerMapping類型的Bean。

也就是說這些HandlerMapping映射處理器的生成是通過在BeanDefinition中匹配,如果匹配上了從單例池中獲取對應(yīng)類型的Bean,因此最后的handlerMappings中就有這5種類型了,至于請求路徑和方法名怎么作為K,V綁定到對應(yīng)映射器上的,由于個人閱讀源碼的能力有限這部分代碼小編還尚未理解,作為小編的一個未解之謎吧。

當(dāng)然,既然5種類型的映射器是通過BD來生成的,那這些BeanDefinition又是什么時候被加到Spring容器中的呢?

這就不得不提一下關(guān)于HandlerMapping映射處理器的配置文件:DispatchServlet.properties文件,這個文件就定義了哪些內(nèi)置使用的組件聲明。

實際上,通過上面源碼的調(diào)試,對于HandlerAdaper的流程和HandlerMapping其實是很類似的。

總結(jié)

(1)handlerMappings映射器集合內(nèi)部一共有5個不同類型的映射器

分別是WebMvcConfigurationSupportXXX,RequestMappingHandlerMapping和BeanNameUrlHandlerMapping,RequestMappingHandlerMapping映射處理器用于使用注解方式請求地址和方法名進(jìn)行映射的Controller,SimpleUrlHandlerMapping用于實現(xiàn)Controller接口或?qū)崿F(xiàn)HttpRequestHandler接口的Controller;

(2)handlerMappings映射器集合初始化會經(jīng)歷一個調(diào)用鏈

在DispatchServlet啟動時自動開始初始化,

HttpServletBean.init-->initServletBean()-->FrameworkServlet.initServletBean--> FrameworkServlet.initWebApplicationContext-->FrameworkServlet.onRefresh -->DispatcherServlet.onRefresh-->DispatcherServlet.initStrategies-->DispatcherServlet.initHandlerMappings -->DispatcherServlet.getDefaultStrategies-->strategies.add((T) strategy)

初始化的結(jié)果是產(chǎn)生一個handlerMappings映射器集合,內(nèi)部包含5種不同類型的映射器,每種映射器內(nèi)部由Map<K,V>來維護(hù)一個<請求地址,全限定方法名>的映射關(guān)系;

(3)handlerMappings映射器集合的每個映射處理器

是在初始化時就生成了BeanDefinition,通過BeanDefinitionName和傳入的type=HandlerMapping類型在所有BeanDefinitionNames集合中匹配所有的映射處理器,再從單例池中獲取其對應(yīng)Bean實例放入handlerMappings中;

(4)對于HandlerAdaper的初始化和HandlerMapping流程是類似的

(5)<請求地址全限定方法名>的映射關(guān)系

在哪里生成并維護(hù)到映射處理器中的,這部分代碼小編暫時還沒能了解到。

三.handlerMappings有什么擴(kuò)展?

我們知道,SpringMVC中不能直接通過url來訪問WEB-INF下的靜態(tài)資源,如我們在工程webapp/jsp/新建一個1.jsp文件,通過

localhost:9090/jsp/1.jsp訪問時會報如下404錯誤

但是SpringBoot卻可以通過url直接訪問webapp,static,resource等包下面的靜態(tài)資源,為什么會這樣呢?原因就在于SpringBoot對SpringMVC的handlerMappings進(jìn)行了自己的拓展。

之所以SpringMVC不能訪問靜態(tài)資源是因為對于這種訪問靜態(tài)資源的請求,在handlerMappings內(nèi)沒有任何一個默認(rèn)的映射器可以進(jìn)行解析處理,因此自然這種請求就會被忽視。

對于SpringBoot來說,它自己實現(xiàn)了一個針對這種訪問靜態(tài)資源的映射處理器并交由handlerMappings來管理,因此就可以做到類似拓展,對于這個知識點在對SpringBoot學(xué)習(xí)時看能否研究一下這個特殊的映射處理器是怎么樣的,這里暫時知道這么一個結(jié)論即可。

到此關(guān)于handlerMappings對象的研究學(xué)習(xí)暫時到此,回到SpringMVC的主線流程邏輯中繼續(xù)學(xué)習(xí)后續(xù)的步驟。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Mybatis的類型轉(zhuǎn)換接口TypeHandler

    Mybatis的類型轉(zhuǎn)換接口TypeHandler

    這篇文章主要介紹了Mybatis的類型轉(zhuǎn)換接口TypeHandler,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下
    2022-08-08
  • Java中StringBuilder字符串類型的操作方法及API整理

    Java中StringBuilder字符串類型的操作方法及API整理

    Java中的StringBuffer類繼承于AbstractStringBuilder,用來創(chuàng)建非線程安全的字符串類型對象,下面即是對Java中StringBuilder字符串類型的操作方法及API整理
    2016-05-05
  • SpringBoot+@EnableScheduling使用定時器的常見案例

    SpringBoot+@EnableScheduling使用定時器的常見案例

    項目開發(fā)中經(jīng)常需要執(zhí)行一些定時任務(wù),本文主要介紹了SpringBoot+@EnableScheduling使用定時器的常見案例,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • IDEA中scala生成變量后自動顯示變量類型問題

    IDEA中scala生成變量后自動顯示變量類型問題

    這篇文章主要介紹了IDEA中scala生成變量后自動顯示變量類型問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • springBoot @Enable* 注解的使用

    springBoot @Enable* 注解的使用

    這篇文章主要介紹了springBoot @Enable* 注解的使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • RxJava2 Scheduler使用實例深入解析

    RxJava2 Scheduler使用實例深入解析

    這篇文章主要為大家介紹了RxJava2 Scheduler使用實例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Java使用HttpClient詳細(xì)示例

    Java使用HttpClient詳細(xì)示例

    這篇文章介紹了Java使用HttpClient的詳細(xì)示例,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • Spring Boot 捕捉全局異常 統(tǒng)一返回值的問題

    Spring Boot 捕捉全局異常 統(tǒng)一返回值的問題

    這篇文章主要介紹了Spring Boot 捕捉全局異常 統(tǒng)一返回值,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • 關(guān)于Spring AOP使用時的一些問題匯總

    關(guān)于Spring AOP使用時的一些問題匯總

    這篇文章主要給大家匯總介紹了關(guān)于Spring AOP使用時的一些問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 簡述mybatis大于小于的轉(zhuǎn)義

    簡述mybatis大于小于的轉(zhuǎn)義

    這篇文章主要介紹了mybatis大于小于的轉(zhuǎn)義以及xml中常用轉(zhuǎn)義字符,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09

最新評論