SpringMVC中的Servlet一共有三個層次,分別是HttpServletBean、FrameworkServlet和 DispatcherServlet。HttpServletBean直接繼承自java的HttpServlet,其作用是將Servlet中配置的參數設置到相應的屬性;FrameworkServlet初始化了WebApplicationContext,DispatcherServlet初始化了自身的9個組件。
本篇博客的內容就是對9個組件做個簡單概述。
在學習9個組件之前,我們需要先了解Handler的概念,也就是處理器。它直接應對着MVC中的C也就是Controller層,它的具體表現形式有很多,可以是類,也可以是方法。在Controller層中@RequestMapping標注的所有方法都可以看成是一個Handler,只要可以實際處理請求就可以是Handler。
(1)HandlerMapping
是用來查找Handler的。在SpringMVC中會有很多請求,每個請求都需要一個Handler處理,具體接收到一個請求之后使用哪個Handler進行處理呢?這就是HandlerMapping需要做的事。
1 public interface HandlerMapping 2 { 3 HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception; 4 }
我們可以看到HandlerMapping接口中只定義了一個方法,就是通過request找到HandlerExecutionChain,而HandlerExecutionChain包裝了一個Handler和一組Interceptors。
(2) HandlerAdapter
從名字上看,它就是一個適配器。因為SpringMVC中的Handler可以是任意的形式,只要能處理請求就ok,但是Servlet需要的處理方法的結構卻是固定的,都是以request和response為參數的方法。如何讓固定的Servlet處理方法調用靈活的Handler來進行處理呢?這就是HandlerAdapter要做的事情。任意形式的Handler通過使用適配器,可以“轉換”成固定形式,然后交給Servlet來處理。每種Handler都要有對應的HandlerAdapter才能處理請求。
1 public interface HandlerAdapter { 2 3 /** 4 * 判斷是否支持傳入的handler 5 */ 6 boolean supports(Object handler); 7 8 /** 9 * 使用給定的handler處理請求 10 */ 11 ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; 12 13 /** 14 * 返回上次修改時間,可以返回-1表示不支持 15 */ 16 long getLastModified(HttpServletRequest request, Object handler); 17 18 }
(3)HandlerExceptionResolver
其它組件都是用來干活的。在干活的過程中難免會出現問題,出問題后怎么辦呢?這就需要有一個專門的角色對異常情況進行處理,在SpringMVC中就是HandlerExceptionResolver。具體來說,此組件的作用是根據異常設置ModelAndView,之后再交給render方法進行渲染。我們來看下HandlerExceptionResolver的接口定義:
1 public interface HandlerExceptionResolver { 2 3 ModelAndView resolveException( 4 HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex); 5 6 }
從上面的分析中我們可以知道HandlerExceptionResolver只能處理頁面渲染之前的異常,頁面渲染過程中的異常,它是不能處理的,這時可以讓容器跳轉到指定的錯誤頁面來處理異常。
(4)ViewResolver
ViewResolver用來將String類型的視圖名和Locale解析為View類型的視圖。View是用來渲染頁面的,也就是將程序返回的參數填入模板里,生成html(也可能是其它類型)文件。這里就有兩個關鍵問題:使用哪個模板?用什么技術(規則)填入參數?這其實是ViewResolver主要要做的工作,ViewResolver需要找到渲染所用的模板和所用的技術(也就是視圖的類型)進行渲染,具體的渲染過程則交由不同的視圖自己完成。
1 public interface ViewResolver { 2 3 View resolveViewName(String viewName, Locale locale) throws Exception; 4 5 }
(5)RequestToViewNameTranslator
ViewName是根據ViewName查找View,但有的Handler處理完后並沒有設置View也沒有設置ViewName,這時就需要RequestToViewNameTranslator從request中找到默認的View了。如何從request中獲取ViewName就是RequestToViewNameTranslator要做的事情了。RequestToViewNameTranslator在Spring MVC容器里只可以配置一個,所以所有request到ViewName的轉換規則都要在一個Translator里面全部實現。
1 public interface RequestToViewNameTranslator { 2 3 String getViewName(HttpServletRequest request) throws Exception; 4 5 }
(6)LocaleResolver
解析視圖需要兩個參數:一是視圖名,另一個是Locale。視圖名是處理器返回的,Locale是從哪里來的?這就是LocaleResolver要做的事情。LocaleResolver用於從request解析出Locale,Locale就是zh-cn之類,表示一個區域,有了這個就可以對不同區域的用戶顯示不同的結果。SpringMVC主要有兩個地方用到了Locale:一是ViewResolver視圖解析的時候;二是用到國際化資源或者主題的時候。
(7)ThemeResolver
用於解析主題。SpringMVC中一個主題對應一個properties文件,里面存放着跟當前主題相關的所有資源、如圖片、css樣式等。SpringMVC的主題也支持國際化,同一個主題不同區域也可以顯示不同的風格。SpringMVC中跟主題相關的類有 ThemeResolver、ThemeSource和Theme。主題是通過一系列資源來具體體現的,要得到一個主題的資源,首先要得到資源的名稱,這是ThemeResolver的工作。然后通過主題名稱找到對應的主題(可以理解為一個配置)文件,這是ThemeSource的工作。最后從主題中獲取資源就可以了。
(8)MultipartResolver
用於處理上傳請求。處理方法是將普通的request包裝成MultipartHttpServletRequest,后者可以直接調用getFile方法獲取File,如果上傳多個文件,還可以調用getFileMap得到FileName->File結構的Map。此組件中一共有三個方法,作用分別是判斷是不是上傳請求,將request包裝成MultipartHttpServletRequest、處理完后清理上傳過程中產生的臨時資源。
(9)FlashMapManager
用來管理FlashMap的,FlashMap主要用在redirect中傳遞參數。