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 在Spring MVC為所有請求入口,标準的servlet。
标準的servlet執行流程為
1.init() 首次加載servlet 整個servlet生命周期隻執行一次
2.service() 依據url-pattern(<url-pattern>/</url-pattern> 攔截所有請求,不包括靜态資源檔案) 攔截模式,比對請求模式,比對成功調用service方法
3.destroy() servlet容器(如:tomcat停止)結束調用
執行流程如下
第一步 執行 HttpServletBean-->init()方法
init()方法我們隻需要關注initServletBean()方法 此方法為抽象方法由FrameworkServlet實作
有興趣的可以具體看一下源碼,整個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:根據注解@RequestMapping生成方法比對政策
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接口 存儲着根據注解@RequestMapping生成方法比對政策
舉個例子
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 />配置完成容器注冊的
轉載于:https://www.cnblogs.com/huxuhong/p/7245690.html