Spring mvc之源碼 handlerMapping和handlerAdapter分析
Spring mvc之源碼 handlerMapping和handlerAdapter分析
本篇並不是具體分析Spring mvc,所以好多細節都是一筆帶過,主要是帶大家梳理一下整個Spring mvc的執行流程,以及如何根據URL查找處理器Controller的實現
(適合那些剛閱讀源碼不知道如何下手的人)
http://www.guojinbao.com/borrow/borrowDetail/GETadLPjnf0[d].do
如何根據URL地址----》找到正確處理器Controller的相應方法Method
註:概念 IOC容器:負責bean的創建和維護bean與bean關系的一個大的集合
①dispatcherServlet
標準的servlet執行流程為
1.init() 首次加載servlet 整個servlet生命周期只執行一次
2.service() 依據url-pattern(<url-pattern>/</url-pattern> 攔截所有請求,不包括靜態資源文件) 攔截模式,匹配請求模式,匹配成功調用service方法
3.destroy() servlet容器(如:tomcat停止)結束調用
執行流程如下
第一步 執行 HttpServletBean-->init()方法
init()方法我們只需要關註
有興趣的可以具體看一下源碼,整個init()方法 為spring mvc的IOC容器初始化
註:Spring 的IOC容器初始化由contextLoaderListener完成
Spring IOC容器建議配置:數據庫連接,事務,與第三方框架集成等等
如:ApplicationContext.xml (小提示:處理器Controller的掃描 可以交給springMVC IOC容器完成,目的分層明確,便於IOC容器查找 )
Spring mvc IOC 容器 配置:
第二部
① FrameworkServlet -->service()
分發請求
② FrameworkServlet--->processRequest(request, response);
③ DispatcherServlet--->doService(HttpServletRequest request, HttpServletResponse response)
如何根據URL找到處理器執行正確的方法就在此方法中
④ DispatcherServlet--->doDispatch(HttpServletRequest request, HttpServletResponse response)
第①部分
這裏為啥不是調用super.service(request,response)?
最直接的理由:如果直接調用service方法 根據method類型進行分發請求就直接跳出框架啦(你懂的嘿嘿)
②③2步有興趣的可以看一下源碼
第④部分
DispatcherServlet--->doDispatch(HttpServletRequest request, HttpServletResponse response)
整個過程如下:
>>1. 獲取url對應的處理器controller以及相應方法
>>2. 獲取執行處理器中方法的對象
>>3. 具體執行
Spring mvc是如何通過URL查找到對應的處理器controller以及對應的方法尼?需要知道以下3個核心接口handlerMapping,handlerAdapter,RequestCondition我們不具體分析相應接口的實現以及具體邏輯,過程相當復雜,1到2句話說
不清楚,這裏給大家留一個直觀的考量。
由於Spring mvc源碼龐大,建議看源碼的時候,只看重點部分或者說自己感興趣部分。我們大家常用是在類和方法加上註解@RequestMapping來標識訪問路徑,我們以此模板給大家量化分析url查詢處理器controller以及相應方法的過程
handlerMapping:負責查找URL對應的處理器Controller
RequestMappingInfo:[email protected]
handlerAdapter:負責綁定參數,執行請求,處理返回值
handlerMapping 接口就一個方法返回HandlerExecutionChain
HandlerExecutionChain
DispatcherServlet--->doDispatch()
第一步 獲取HandlerExecutionChain
在DispatcherServlte的servlet初始化中(調用init()方法)中調用onRefresh()完成handlerMappings的初始化
第二步 獲取handlerAdapter 找到和handlerMapping匹配的handlerAdapter
初始化過程同第一步
DispatcherServlte會根據handlerMapping與已經註冊好了的HandlerAdapter一一匹配,看哪一種HandlerAdapter是支持該handlerMapping類型的,
如果找到了其中一種HandlerAdapter是支持傳過來的handlerMapping類型,那麽該HandlerAdapter會調用自己的handle方法,handle方法運用Java的反射機制執行controller的具體方法來獲得ModelAndView
以handlerMapping的實現RequestMappingHandlerMapping為例
由於實現了InitializingBean,當RequestMappingHandlerMapping完成bean的初始化後,會調用afterPropertiesSet()-->initHandlerMethods();完成以下操作
①生成直接URL-->RequestMappingInfo,映射操作
②生成 RequestMappingInfo--->handlerMethod映射操作
③將所有的RequestMappingInfo註冊到容器中
註:
RequestMappingInfo實現了RequestCondition接口 存儲著[email protected]
舉個例子
PatternsRequestCondition的初始化相當於
PatternsRequestCondition(“/user/applicationShow/{id}”)當請求URL符合此規則是就匹配成功
簡單滴說,RequestMappingInfo是將註解@RequestMapping的信息提取出來
生成此方法的匹配條件
閱讀RequestMappingHandlerMapping源碼流程如下(主要是為了梳理出重點部分)
綜上所述我們來猜測一下spring mvc 中根據URL找到處理器Controller中相應方法的流程
①:獲取Request的URL
②:從UrlLookup這個map中找到相應的requestMappingInfo
③:如果沒找到則遍歷所有requestMappingInfo的信息直到找到匹配的requestMappingInfo
④:根據requestMappingInfo到mappingLookup中找到handlerMethod
handlerMethod接口如下:
到這裏大家差不多就明白了吧,有了處理器實例,方法,參數調用反射執行方法分分鐘的事情
當然spring mvc真正執行比這個復雜的多啦,但是執行的時候是逃不出這個套路的。
具體的URL找到處理器Controller中相應方法的流程請大家看一下DispatcherServlet--》getHandler()方法
註:
最後說一下RequestMappingHandlerMapping並不是默認的查找處理器方法的策略,他是通過 <mvc:annotation-driven />配置完成容器註冊的
Spring mvc之源碼 handlerMapping和handlerAdapter分析