Spring MVC 與 Web
IoC容器與Web容器的關係
ServletContext為IoC容器提供了宿主環境。IoC容器通過ContexLoaderListener初始化建立,ContexLoaderListener是註冊在Web容器中的監聽器,當Web容器初始化時,監聽器會收到該事件從而發起Spring容器的初始化。DispatchServlet是Spring MVC處理請求的轉發器,從而響應HTTP的請求。
ContexLoaderListener會呼叫ContextLoader,ContextLoader又會建立XmlWebApplicationContext,XmlWebApplicationContext作為預設的IoC容器,負責從預設的/WEB-INF/applicationContext.xml
中載入BeanDefinition。
ContextLoader在建立IoC容器XmlWebApplicationContext後會將其註冊入servletContext的屬性ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
中。
DispatchServlet的功能
DispatchServlet負責兩個工作,根據web.xml初始化自己的上下文,響應http請求。
在ContextLoader載入完成後,開始DispatchServlet的初始化。首先從ServletContext中獲取WebApplicationContext作為雙親上下文,這裡就是XmlWebApplicationContext,所以XmlWebApplicationContext定義的Bean可以被DispatchServlet獲取,在DispatchServlet中查詢Bean時,會首先從雙親上下文中查詢。獲取雙親上下文後,DispatchServlet會建立自己的上下文,並且將其註冊進ServletContext的屬性中,屬性名為該servlet相關的,因為一個Web容器可以有多個servlet。
DispatchServlet上下文的初始化後會開始建立一些請求處理策略,如LocalResolver、HandlerMappings等。例如,初始化HandlerMappings就是從IoC容器中獲取所有的HandlerMapping相關的Bean。
HandlerMapping是對HTTP請求到controller的對映,HandlerMapping根據請求獲取一個HandlerExecutionChain,其中包含了一個handler和多個interceptor,interceptor負責功能的增強。
例如SimpleUrlHandlerMapping在初始化時會將url和對應handler的bean放入map中儲存。當請求到達時,會從SimpleUrlHandlerMapping中查詢最長匹配url的handler,包裝成HandlerExecutionChain返回。
DispatchServlet處理請求的過程
當請求到來,從所有的HandleMapping中依次查詢到匹配的HandlerExecutionChain,多個HandleMapping是按照優先順序排序的。
HandlerExecutionChain獲得後,先對請求執行intercepter的preHandler,然後執行handler,最後再次執行intercepter的postHandler,得到最終的ModelAndView物件。
最後根據ModelAndView渲染檢視並返回。
ModelAndView呈現給客戶端的過程
以JSP檢視為例。
Step1:ModelAndView獲得後,會從中獲取其對應的View,也就是根據ModelAndView指明的名稱獲得對應View的Bean。
Step2:View接著將資料進行合併,然後將資料放入requst中進行暴露。
Step3:根據請求,獲取URL路徑,定位資源。如JSP檔案。
Step4:將包含資料的requst轉發到目標資源路徑,由web容器負責獲取資源,並且將資料裝入JSP。最後將拼裝好的檔案返回。