Spring?MVC啟動(dòng)之HandlerMapping作用及實(shí)現(xiàn)詳解
引言
在上一篇文章中,我們介紹了 Spring MVC 的啟動(dòng)流程,接下來我們將發(fā)分多個(gè)篇章詳細(xì)介紹流程中的重點(diǎn)步驟
今天我們從 HandlerMapping 開始分析,HandlerMapping 是框架中的一個(gè)非常重要的組件。它的作用是將URL請(qǐng)求映射到合適的處理程序(Handler)上,這樣就能夠?qū)崿F(xiàn)控制器與頁面之間的交互。在 Spring MVC 中,有多種不同的 HandlerMapping 實(shí)現(xiàn),本文將對(duì)這些實(shí)現(xiàn)的作用和源碼原理進(jìn)行詳細(xì)介紹。
作用
在 Spring MVC 框架中,HandlerMapping 是一個(gè)非常重要的組件,它的作用是將URL請(qǐng)求映射到相應(yīng)的處理程序上。具體來說,HandlerMapping 會(huì)根據(jù)URL請(qǐng)求的路徑、請(qǐng)求參數(shù)等信息,確定需要執(zhí)行哪個(gè)處理程序,并將該處理程序返回給 DispatcherServlet。然后 DispatcherServlet 再將請(qǐng)求分配給相應(yīng)的處理程序,處理程序處理完請(qǐng)求后,將結(jié)果返回給 DispatcherServlet,DispatcherServlet 再將結(jié)果返回給客戶端。
HandlerMapping的實(shí)現(xiàn)
Spring MVC 框架中有多種不同的 HandlerMapping 實(shí)現(xiàn),每種實(shí)現(xiàn)都有不同的作用和使用場(chǎng)景。下面將逐一介紹這些實(shí)現(xiàn)。
BeanNameUrlHandlerMapping
BeanNameUrlHandlerMapping 是 Spring MVC 框架中最簡(jiǎn)單的 HandlerMapping 實(shí)現(xiàn),它的作用是將 URL 請(qǐng)求的路徑映射到 Bean 的名稱上。具體來說,當(dāng)請(qǐng)求的路徑與一個(gè) Bean 的名稱匹配時(shí),BeanNameUrlHandlerMapping 會(huì)將該請(qǐng)求映射到對(duì)應(yīng)的 Bean 上。
例如:
假設(shè)有一個(gè)名為 "/hello" 的請(qǐng)求
我們可以在 Spring 配置文件中定義一個(gè)名為 "helloController" 的 Bean
然后使用 BeanNameUrlHandlerMapping 將 "/hello" 請(qǐng)求映射到該 Bean 上
這樣,當(dāng)客戶端發(fā)送 "/hello" 請(qǐng)求時(shí),DispatcherServlet 就會(huì)將該請(qǐng)求分配給 "helloController" 處理。
BeanNameUrlHandlerMapping 的源碼比較簡(jiǎn)單,它的核心代碼如下所示:
public class BeanNameUrlHandlerMapping extends AbstractUrlHandlerMapping { protected Object getHandlerInternal(HttpServletRequest request) throws Exception { String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); return obtainHandler(lookupPath, request); } }
從代碼中可以看出,BeanNameUrlHandlerMapping 實(shí)現(xiàn)了 AbstractUrlHandlerMapping 接口,并重寫了其中的 getHandlerInternal 方法。該方法的作用是根據(jù)請(qǐng)求的 URL 路徑查找相應(yīng)的處理程序。
SimpleUrlHandlerMapping
SimpleUrlHandlerMapping 是 Spring MVC 框架中另一種常用的 HandlerMapping 實(shí)現(xiàn),它的作用是將 URL 請(qǐng)求的路徑映射到處理程序上。與 BeanNameUrlHandlerMapping 不同的是,SimpleUrlHandlerMapping 可以將一個(gè)URL請(qǐng)求映射到多個(gè)處理程序上。
例如:
假設(shè)有兩個(gè)請(qǐng)求 "/hello" 和 "/world"
我們可以使用 SimpleUrlHandlerMapping 將這兩個(gè)請(qǐng)求分別映射到不同的處理程序上。具體來說,我們可以在 Spring 配置文件中定義多個(gè) Bean,并分別為它們?cè)O(shè)置不同的URL路徑。
然后使用 SimpleUrlHandlerMapping 將這些URL路徑與相應(yīng)的處理程序進(jìn)行映射。
這樣,當(dāng)客戶端發(fā)送一個(gè)請(qǐng)求時(shí),SimpleUrlHandlerMapping 就會(huì)根據(jù)請(qǐng)求的URL路徑查找相應(yīng)的處理程序,并將請(qǐng)求分配給該處理程序處理。
SimpleUrlHandlerMapping 的源碼也比較簡(jiǎn)單,它的核心代碼如下所示:
public class SimpleUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping { protected Object getHandlerInternal(HttpServletRequest request) throws Exception { String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); Object handler = lookupHandler(lookupPath, request); if (handler == null) { handler = getDefaultHandler(); } return handler; } }
從代碼中可以看出,SimpleUrlHandlerMapping 同樣實(shí)現(xiàn)了 AbstractUrlHandlerMapping 接口(在 AbstractDetectingUrlHandlerMapping 中繼承),并重寫了其中的 getHandlerInternal 方法。該方法的作用是根據(jù)請(qǐng)求的URL路徑查找相應(yīng)的處理程序。
ControllerClassNameHandlerMapping
ControllerClassNameHandlerMapping 是Spring MVC 框架中一種比較特殊的 HandlerMapping 實(shí)現(xiàn),它的作用是將URL請(qǐng)求的路徑映射到 Controller 類名上。具體來說,ControllerClassNameHandlerMapping 會(huì)根據(jù)請(qǐng)求的URL路徑查找對(duì)應(yīng)的 Controller 類名,并將該類返回給 DispatcherServlet,然后 DispatcherServlet 再將請(qǐng)求分配給該 Controller 類處理。
例如:
假設(shè)有一個(gè)名為 "/hello" 的請(qǐng)求
我們可以定義一個(gè)名為 HelloController的Controller 類
使用 ControllerClassNameHandlerMapping 將 "/hello" 請(qǐng)求映射到該類上。
這樣,當(dāng)客戶端發(fā)送 "/hello" 請(qǐng)求時(shí),ControllerClassNameHandlerMapping 就會(huì)將該請(qǐng)求映射到 HelloController 處理。
ControllerClassNameHandlerMapping 的源碼也比較簡(jiǎn)單,它的核心代碼如下所示:
public class ControllerClassNameHandlerMapping extends AbstractControllerUrlHandlerMapping { protected Object getHandlerInternal(HttpServletRequest request) throws Exception { String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); String controllerClassName = getClassNameForUrlPath(lookupPath); return obtainApplicationContext().getBean(controllerClassName); } }
從代碼中可以看出,ControllerClassNameHandlerMapping 同樣實(shí)現(xiàn)了 AbstractUrlHandlerMapping 接口,并重寫了其中的 getHandlerInternal 方法。該方法的作用是根據(jù)請(qǐng)求的URL路徑查找相應(yīng)的 Controller 類名,并將該類返回給 DispatcherServlet。
DefaultAnnotationHandlerMapping
DefaultAnnotationHandlerMapping 是Spring MVC 框架中另一種比較常用的 HandlerMapping實(shí) 現(xiàn),它的作用是將 URL 請(qǐng)求的路徑映射到標(biāo)注了 @RequestMapping 注解的方法上。
具體來說,DefaultAnnotationHandlerMapping 會(huì)掃描應(yīng)用程序中所有標(biāo)注了 @RequestMapping 注解的方法,并將這些方法與相應(yīng)的URL路徑進(jìn)行映射。
然后當(dāng)客戶端發(fā)送一個(gè)請(qǐng)求時(shí),DefaultAnnotationHandlerMapping 就會(huì)根據(jù)請(qǐng)求的URL路徑查找相應(yīng)的處理程序,并將該處理程序返回給 DispatcherServlet,然后 DispatcherServlet 再將請(qǐng)求分配給該處理程序處理。
例如:
假設(shè)有一個(gè)名為 "/hello" 的請(qǐng)求
我們可以在 Controller 類的某個(gè)方法上標(biāo)注 @RequestMapping 注解
將該方法與 "/hello" 請(qǐng)求進(jìn)行映射。
這樣,當(dāng)客戶端發(fā)送 "/hello" 請(qǐng)求時(shí),DefaultAnnotationHandlerMapping 就會(huì)將該請(qǐng)求映射到該方法上,然后將該方法返回給 DispatcherServlet 處理。
DefaultAnnotationHandlerMapping 的源碼比較復(fù)雜,因?yàn)樗枰獟呙钁?yīng)用程序中所有標(biāo)注了 @RequestMapping 注解的方法。其核心代碼如下所示:
public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandlerMapping implements BeanFactoryAware, InitializingBean { private final List<RequestMappingInfoHandlerMapping> handlerMappings = new ArrayList<>(); protected Object getHandlerInternal(HttpServletRequest request) throws Exception { for (RequestMappingInfoHandlerMapping hm : this.handlerMappings) { HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } return null; } public void afterPropertiesSet() throws Exception { initHandlerMethods(); } protected void initHandlerMethods() { detectHandlerMethods(); if (logger.isInfoEnabled()) { logger.info("Mapped " + this.handlerMethods.size() + " request handler methods"); } } protected void detectHandlerMethods() { ... } }
從代碼中可以看出,DefaultAnnotationHandlerMapping 同樣實(shí)現(xiàn)了 AbstractUrlHandlerMapping 接口,并重寫了其中的 getHandlerInternal 方法。該方法的作用是根據(jù)請(qǐng)求的 URL 路徑查找相應(yīng)的處理程序。
與其他 HandlerMapping 不同的是,DefaultAnnotationHandlerMapping 還實(shí)現(xiàn)了 BeanFactoryAware和InitializingBean 接口,以便在初始化時(shí)掃描應(yīng)用程序中所有標(biāo)注了 @RequestMapping 注解的方法。
具體來說,它會(huì)調(diào)用 detectHandlerMethods 方法,對(duì)應(yīng)用程序中所有標(biāo)注了 @RequestMapping 注解的方法進(jìn)行掃描,并將這些方法與相應(yīng)的URL路徑進(jìn)行映射。
總結(jié)
在 Spring MVC 框架中,HandlerMapping 用于將URL請(qǐng)求的路徑映射到相應(yīng)的處理程序上。框架中提供了多種不同的 HandlerMapping 實(shí)現(xiàn),包括 BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping、ControllerClassNameHandlerMapping 和 DefaultAnnotationHandlerMapping 等。不同的HandlerMapping 實(shí)現(xiàn)方式適用于不同的應(yīng)用場(chǎng)景。
- BeanNameUrlHandlerMapping 是最簡(jiǎn)單的HandlerMapping實(shí)現(xiàn),它將 URL 請(qǐng)求的路徑直接映射到 Bean 的名稱上。
- SimpleUrlHandlerMapping 則將 URL 請(qǐng)求的路徑與相應(yīng)的處理程序進(jìn)行映射。
- ControllerClassNameHandlerMapping 將 URL 請(qǐng)求的路徑映射到 Controller 類名上。
- DefaultAnnotationHandlerMapping 則將 URL 請(qǐng)求的路徑映射到標(biāo)注了 @RequestMapping 注解的方法上。
無論是哪種 HandlerMapping 實(shí)現(xiàn)方式,它們都遵循相同的流程來處理請(qǐng)求。具體來說,它們的流程如下:
客戶端發(fā)送請(qǐng)求到DispatcherServlet。
- DispatcherServlet根據(jù)請(qǐng)求的URL路徑選擇相應(yīng)的HandlerMapping。
- HandlerMapping將請(qǐng)求的URL路徑與相應(yīng)的處理程序進(jìn)行映射。
- HandlerMapping返回相應(yīng)的處理程序。
- DispatcherServlet將請(qǐng)求交給相應(yīng)的處理程序進(jìn)行處理。
- 處理程序進(jìn)行業(yè)務(wù)邏輯的處理,并返回相應(yīng)的結(jié)果。
- DispatcherServlet將處理程序的結(jié)果進(jìn)行封裝,并返回給客戶端。
以上就是Spring MVC啟動(dòng)之HandlerMapping作用及實(shí)現(xiàn)詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring MVC啟動(dòng)HandlerMapping的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springboot實(shí)現(xiàn)防重復(fù)提交和防重復(fù)點(diǎn)擊的示例
這篇文章主要介紹了springboot實(shí)現(xiàn)防重復(fù)提交和防重復(fù)點(diǎn)擊的示例,幫助大家更好的理解和學(xué)習(xí)springboot框架,感興趣的朋友可以了解下2020-09-09Spring MVC實(shí)現(xiàn)一次簡(jiǎn)單的CRUD示例
這篇文章主要介紹了Spring MVC實(shí)現(xiàn)一次簡(jiǎn)單的CRUD示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08hadoop的hdfs文件操作實(shí)現(xiàn)上傳文件到hdfs
這篇文章主要介紹了使用hadoop的API對(duì)HDFS上的文件訪問,其中包括上傳文件到HDFS上、從HDFS上下載文件和刪除HDFS上的文件,需要的朋友可以參考下2014-03-03SpringMVC自定義參數(shù)綁定實(shí)現(xiàn)詳解
這篇文章主要介紹了SpringMVC自定義參數(shù)綁定實(shí)現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11eclipse實(shí)現(xiàn)可認(rèn)證的DH密鑰交換協(xié)議
這篇文章主要介紹了eclipse實(shí)現(xiàn)可認(rèn)證的DH密鑰交換協(xié)議,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06Java探索之Thread+IO文件的加密解密代碼實(shí)例
這篇文章主要介紹了Java探索之Thread+IO文件的加密解密代碼實(shí)例,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10