spring學習筆記之DispatcherServlet源碼解讀

DispatcherServlet--翻譯spring-framework-reference.pdf及源碼解讀。


最近在看spring源碼,同時也看着英文版的spring-framework-reference.pdf。順便花點時間翻譯下來,一方面記錄下學習路程,另一方面加深印象。


spring web MVC 框架,就像其他web MVC框架一樣,是請求驅動,圍繞一個核心的servlet設計,這個servlet把接收的請求(request)分別分發到不同的控制器並提供其他功能促進web應用的開發。而spring的DispatcherServlet做的事情更多。它完全整合了spring Ioc容器方便你使用spring所擁有的功能。

這幅圖解釋了spring web MVC DispatcherServlet對請求的處理流程。其實DispatcherServlet是採用了前端控制器(Front Controller)的設計模式,這種設計模式也被其他流行的web框架所採用。

DispatcherServlet層次類圖

根據類圖,知道DispatcherServlet實際上是一個Servlet,因爲它繼承於HttpServlet,所以它需要在web.xml定義,並且在web.xml定義需要通過DispatherServlet處理的請求的URL映射。

這是標準的J2EE servlet 配置方式。下面是一個例子:



       上面這個例子,所有以.form結尾的請求都會被名爲example的DispaterServlet處理。這是使用spring MVC的第一步,一系列beans需要配置。

       在spring web MVC框架,每一個DispatcherServlet都有它自己的WebApplicationContext,這些WebApplicationContext繼承了一個根WebApplicationContextde定義的所有bean。這些被繼承的bean可以在具體的servlet中改寫作用域,也可以在一個servlet實例定義新的局部的作用域bean。

       框架在啓動初始化DispatcherServlet時,在WEB應用下的WEB-INF目錄下尋找名爲[servlet-name]-servlet.xml的文件,並創建定義的bean,這些bean如果同樣在全局作用域中定義(名字相同),則覆蓋全局bean.如在上一例中,則會找WEB-INF/example-servlet.xml文件。當然,配置文件的路徑可以通過servlet的參數配置。

       WebApplicationContext是普通的ApplicationContext的擴展,它增加了一些web應用需要的特性。比如,它解析themes與ApplicationContext是不同的,因爲它會關聯到ServletContext。WebApplicationContext綁定到了ServletContext,在你需要訪問它時,只需要用RequestContextUtils類的靜態方法就可以找到它。

       DispatcherServlet有幾個特殊的bean用來處理request請求和渲染適合的視圖。這些bean包含在spring框架中,並可在WebApplicationContext像其他普通bean一樣配置。在下面有更具體的介紹。

Bean類型

說明

Controllers

MVC架構的'C'

Handler mappings

主要負責預處理,後置處理等一系列執行處理和滿足特定條件下的控制器的執行,比如URL匹配等

View resolvers

負責根據視圖名稱解析視圖

Locale resolver

負責語言本地化

Theme resolver

負責根據應用使用解析主題,比如可以定製個性化版面

multipart file


resolver


負責在html頁面提供文件上傳功能

Handler exception resolver(s)

負責提供處理異常功能

DispatcherServlet服務啓動,一個請求到特定的DispatcherServlet,這時Dispatcher開始處理請求。下面是DispatcherServlet處理請求的完整過程。

1.尋找WebApplicationContext並且在request作爲一個屬性綁定方便控制器和其他成員使用。默認的綁定KEY是  DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE.

2.本地化解析器綁定到request中。如果沒有使用該解析器,則不作任何事情。

3.主題解析器綁定到request中。如果沒有使用該解析器,則不做任何事情。

4.如果multipart resolver被指定,則request會檢測它。如果找到,request被包裝成MultipartHttpServletRequest方便之後的其他成員處理。

5.尋找合適的的處理模塊。如果找到,該處理模塊相關的執行鏈如預處理,後置處理和控制器等都會被執行爲模塊的渲染作準備。

6.如果一個模塊返回,則會渲染一個視圖。如果沒有模塊返回,就沒有視圖被渲染,因爲請求可能已經處理完成。

處理請求過程中拋出異常,請求會啓用在WebApplicationContext聲明的異常處理解析器。在發生異常時,可以使用這些解析器定義用戶的行爲。

DispatcherServlet也支持返回last-modification-date。DispatcherServlet首先尋找一個合適的處理映射並檢測這處理模塊是否實現了LastModified接口。如果是,這個接口的方法long getLastModified(request)返回值給客戶端。

你也可以定製DispatcherServlet,通過在web.xml或者servlet初始參數上添加上下文容器的參數。具體如下:

參數

說明

contextClass

實現了WebApplicationContext接口的類,用來初始上下文環境。如果沒有指定,則默認XmlWebApplicationContext

contextConfigLocation

傳遞給context實例的字符串,說明哪裏可以找到context。這個字符串可被逗號拆分從而支持多個contexts。

namespace

WebApplicationContext命名空間。默認是 [servlet-name]-servlet



現在再查看源碼加深理解。

首先服務器如tomcat啓動時,就會將web.xml定義的context的bean都會實例化。入口當然是

org.springframework.web.servlet.DispatcherServlet。它是一個HttpServlet,所以必然會執行init()方法。我們查看根據上述的DispatcherServlet類圖查看,發現HttpServletBean纔有init()方法。


 

在這個方法裏最重要的是initServletBean()。它會調用FrameworkServlet下的initServletBean(),這個方法改寫了HttpServletBean的initServletBean()。代碼如下:

 

 

 

我們應該注意到這個方法有修飾符final,是不能子類重寫的,這就體現了 “開-閉原則(open for extension,close for modification)”我們再看initWebApplicationContext()


FindWebApplicationContext() 方法是從 ServletContext 屬性取 WebApplicationContext ,如果沒有配置 ServletContext 屬性的話,則返回 null 。這時,先取回根 WebApplicationContext,key 是 WebApplicationContext. ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE

 

createWebApplicationContext(parent) 方法是真正得到我們 DispatcherServlet 對應的 WebApplicationContext

 

 

在這個方法裏,首先調用 getContextClass() 獲取默認的 ContextClass, 就是 public static final Class DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext. class

 

這行代碼就是利用 XmlWebApplicationContext 的無參數構造函數實例化 XmlWebApplicationContext 因爲 XmlWebApplicationContext 實現了 ConfigurableWebApplicationContext 接口。接下來就是填充 XmlWebApplicationContext 的屬性,這些屬性部分在上面有提及過。這樣在這個 WebApplicationContext 就可以使用了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章