中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringMVC中的handlerMappings對象怎么用

發布時間:2021-09-26 15:51:03 來源:億速云 閱讀:128 作者:小新 欄目:開發技術

這篇文章給大家分享的是有關SpringMVC中的handlerMappings對象怎么用的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

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

SpringMVC中的handlerMappings對象怎么用

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

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

SpringMVC中的handlerMappings對象怎么用

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

主要有以下兩種內置類型:

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

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

SpringMVC中的handlerMappings對象怎么用

一.handlerMappings集合內部的元素是什么,有什么作用?

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

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

對于RequestMappingHandlerMapping

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

SpringMVC中的handlerMappings對象怎么用

對于SimpleUrlHandlerMapping

這個映射器則是為繼承Controller類或實現HttpRequestHandler接口的類進行解析和映射處理的。

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

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

SpringMVC中的handlerMappings對象怎么用

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

SpringMVC中的handlerMappings對象怎么用

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

SpringMVC中的handlerMappings對象怎么用

SpringMVC中的handlerMappings對象怎么用

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

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

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

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

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

我們的目的是找到哪里進行了handlerMappings的核心操作,通過調用關系我們找到核心代碼在DispatcherServlet.initHandlerMappings:

SpringMVC中的handlerMappings對象怎么用

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

SpringMVC中的handlerMappings對象怎么用

SpringMVC中的handlerMappings對象怎么用

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

SpringMVC中的handlerMappings對象怎么用

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

lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit)

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

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

SpringMVC中的handlerMappings對象怎么用

SpringMVC中的handlerMappings對象怎么用

SpringMVC中的handlerMappings對象怎么用

SpringMVC中的handlerMappings對象怎么用

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

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

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

SpringMVC中的handlerMappings對象怎么用

SpringMVC中的handlerMappings對象怎么用

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

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

SpringMVC中的handlerMappings對象怎么用

SpringMVC中的handlerMappings對象怎么用

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

總結

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

分別是WebMvcConfigurationSupportXXX,RequestMappingHandlerMapping和BeanNameUrlHandlerMapping,RequestMappingHandlerMapping映射處理器用于使用注解方式請求地址和方法名進行映射的Controller,SimpleUrlHandlerMapping用于實現Controller接口或實現HttpRequestHandler接口的Controller;

(2)handlerMappings映射器集合初始化會經歷一個調用鏈

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

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

初始化的結果是產生一個handlerMappings映射器集合,內部包含5種不同類型的映射器,每種映射器內部由Map<K,V>來維護一個<請求地址,全限定方法名>的映射關系;

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

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

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

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

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

三.handlerMappings有什么擴展?

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

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

SpringMVC中的handlerMappings對象怎么用

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

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

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

感謝各位的閱讀!關于“SpringMVC中的handlerMappings對象怎么用”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

桐柏县| 论坛| 茂名市| 长岭县| 宿州市| 偏关县| 克山县| 米易县| 阳高县| 博兴县| 志丹县| 翁牛特旗| 奉节县| 延边| 明光市| 汕头市| 渭南市| 图木舒克市| 东源县| 澄迈县| 普宁市| 确山县| 柘荣县| 南充市| 项城市| 江阴市| 苗栗县| 宜州市| 天台县| 华阴市| 华安县| 贵南县| 桐城市| 察雅县| 武城县| 湟中县| 磐石市| 蒙山县| 建水县| 平谷区| 怀安县|