Spring MVC是創建在IOC容器基礎上的。前端
DispachServlet和ContextLoaderListener提供在Web容器中對Spring的接口,這些接口與Web容器耦合是經過ServletContext來實現,ServletContext爲Spring的IOC容器提供了一個宿主環境,Spring MVC創建起一個IOC容器體系。ContextLoaderListener定義爲監聽器,負責完成IOC容器在Web環境中的啓動工做。 DispatcherServlet起着分發請求的做用,定義了對應的URL映射。java
<servlet> <servlet-name>SpringDispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>SpringDispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
IOC容器的啓動過程就是創建上下文的過程,與ServletContext相伴而生。web
spring使用默認的XmlWebApplicationContext做爲IOC容器。spring
ContextLoaderListener的做用就是啓動啓動IOC容器並將其載入到WEB容器,是整個sping web應用加載IOC容器的第一個地方。它實現了ServletContextListener接口,提供了與servlet生命週期結合的回調(contextInitialized, contextDestroyed)。ContextLoaderListener啓動創建的上下文爲根上下文,DispatcherServlet所建立的上下文的的父上下文即爲此根上下文。具體的載入IOC容器的過程交由它的基類ContextLoader完成。設計模式
ContextLoader完成兩個IOC容器的創建,一個是在Web容器中創建雙親IOC容器,另外一個生成相應的WebApplicationContext並初始化。app
DispatcherServlet會創建本身的上下文持有Spring MVC的Bean對象,在創建本身持有的這個IOC容器的時候,會從ServletContext中獲得根上下文來做爲DispatcherServlet持有的上下文的雙親上下文。最後把本身的上下文保存到ServletContext中。框架
、jsp
DispacherServlet的工做主要分爲兩個部分:一是初始化部分,由initServletBean()啓動,經過initWebApplicationContext()最終調用DispatcherServlet的initStrategies()方法,對MVC模塊的其餘部分進行初始化(好比國際化、支持request映射的HandlerMapping等);另外一個是對HTTP請求進行相應,做爲Servlet,Web容器會調用Servlet的doGet()和doPost()方法,最終會調用DispatcherServlet的doService()方法,而後調用其封裝的doDispacher()方法。post
//MVC框架的初始化 protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
在DispatcherServlet類的doService方法中,首先爲Request請求設置了一些對應的屬性實例,而後調用doDispatch方法去分發處理請求。如下是實際處理過程:url
1.在doDispatch方法中,調用checkMultipart方法去判斷該請求是不是Multipart請求(好比文件上傳),若是是,則使用MultipartResolver實例將請求轉換爲Multipart請求。
2.調用getHandler方法去獲取HandlerExecutionChain實例對象。在該方法中首先查找符合當前的HandlerMapping實例,而後調用HandlerMapping實例getHandler方法去獲取HandlerExecutionChain實例,該實例包裝了HandlerMapping實例對象,並在該實例中設置了相匹配的攔截器。
3.調用getHandlerAdapter方法,爲當前HandlerMapping實例查找對應的HandlerAdapter適配器實例。
4.調用HandlerExecutionChain實例的applyPreHandler方法,去調用其攔截器的preHandler方法(前置攔截方法)執行。若是返回true,則繼續日後處理,不然中止方法調用處理。(前置攔截方法執行調用)
5.調用HandlerAdapter適配器實例的handler方法去處理當前請求,並返回對應的ModelAndView對象。(調用目標對象的對應方法執行)
6.調用HandlerExecutionChain實例的applyPostHandler方法,去調用其攔截器的postHandler方法(後置攔截方法)執行。(後置攔截方法執行調用)
7.調用processDispatchResult方法去處理最後結果(ModelAndView或者異常),該方法調用render方法去渲染解析最後視圖。在render方法中首先經過ViewResolver解析器去獲取對應的視圖名稱的視圖View對象,最後在調用對應View對象的render方法渲染處理視圖,並響應對應結果給客戶端。(調用對應View渲染視圖)
DispatcherServlet默認使用WebApplicationContext做爲上下文,所以咱們來看一下該上下文中有哪些特殊的Bean:
1、Controller:處理器/頁面控制器,作的是MVC中的C的事情,但控制邏輯轉移到前端控制器了,用於對請求進行處理;
2、HandlerMapping:請求處處理器的映射,若是映射成功返回一個HandlerExecutionChain對象(包含一個Handler處理器(頁面控制器)對象、多個HandlerInterceptor攔截器)對象;如BeanNameUrlHandlerMapping將URL與Bean名字映射,映射成功的Bean就是此處的處理器;
3、HandlerAdapter:HandlerAdapter將會把處理器包裝爲適配器,從而支持多種類型的處理器,即適配器設計模式的應用,從而很容易支持不少類型的處理器;如SimpleControllerHandlerAdapter將對實現了Controller接口的Bean進行適配,而且掉處理器的handleRequest方法進行功能處理;
4、ViewResolver:ViewResolver將把邏輯視圖名解析爲具體的View,經過這種策略模式,很容易更換其餘視圖技術;如InternalResourceViewResolver將邏輯視圖名映射爲jsp視圖;
5、LocalResover:本地化解析,由於Spring支持國際化,所以LocalResover解析客戶端的Locale信息從而方便進行國際化;
6、ThemeResovler:主題解析,經過它來實現一個頁面多套風格,即常見的相似於軟件皮膚效果;
7、MultipartResolver:文件上傳解析,用於支持文件上傳;
8、HandlerExceptionResolver:處理器異常解析,能夠將異常映射到相應的統一錯誤界面,從而顯示用戶友好的界面(而不是給用戶看到具體的錯誤信息);
9、RequestToViewNameTranslator:當處理器沒有返回邏輯視圖名等相關信息時,自動將請求URL映射爲邏輯視圖名;
10、FlashMapManager:用於管理FlashMap的策略接口,FlashMap用於存儲一個請求的輸出,當進入另外一個請求時做爲該請求的輸入,一般用於重定向場景,後邊會細述。