1. 程式人生 > >Spring4.3.8MVC中文文件-22.2-The DispatcherServlet-前置控制器

Spring4.3.8MVC中文文件-22.2-The DispatcherServlet-前置控制器

        SpringMVC就像其它WebMVC框架一樣,以請求為驅動,圍繞一箇中央Servlet派遣請求給控制層,和提供一些其它的有助於Web應用程式開發的功能。但是,Spring前置控制器不僅僅做了這些。 他完全集成了SpringIOC容器,因此你還可以使用Spring框架的一些特性

      SpringMVC前置控制器(DispatcherServlet)對請求的處理流程參見下圖。對模式非常瞭解的讀者可能會意識到,所謂的DispatcherServlet是“前置控制器”設計模式的表達 (這是SpringMVC和其它許多優秀網頁框架都採用的模式)

       DispatcherServlet實際上是一個Servlet(它繼承自HttpServlet基類),因此你需要在你的網頁應用中宣告。你需要對希望被DispatcherServlet處理的請求進行URL對映。 這是JavaEE Servlet在Servlet 3.0版本以上的標配

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
        ServletRegistration.Dynamic registration = container.addServlet("example", new DispatcherServlet());
        registration.setLoadOnStartup(1);
        registration.addMapping("/example/*");
    }

}

       在上面這個例子,所有的請求以/example開頭就會被名為example的DispatcherServlet例項處理

      WebApplicationInitializer是一個SpringMVC提供的介面,用來確保你的基於程式碼的配置在任何Servlet3容器中能被檢測並自動初始化。 一個名為AbstractAnnotationConfigDispatcherServletInitializer的介面的抽象基類通過實現指定其servlet對映並列出配置類來更容易的註冊DispatcherServlet。它甚至推薦你去設定你的SpringMVC應用。

      DispatcherServlet實際上就是一個Servlet(它繼承自HttpServlet基類),因此它在你的web應用中的web.xml宣告。同樣,你也要在web.xml中通過URL對映需要被dispacherServlet處理的請求。 這是javaEE Servlet的標準配置。在接下來的例子展示DispatcherServlet的宣告和對映

    接下來的Web.xml相當於上面java程式碼的例子

<web-app>
    <servlet>
        <servlet-name>example</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>example</servlet-name>
        <url-pattern>/example/*</url-pattern>
    </servlet-mapping>

</web-app>
       詳細資訊在7.15章節Additional Capabilities of the ApplicationContext,Spring中的ApplicationContext例項能被限定。在Web MVC框架中,每個DispatcherServlet都有自己的WebApplicationContext, 它繼承了已經在根WebApplicationContext中定義的所有bean。根WebApplicationContext應該包含所有的在其它的上下文和servlet例項中共享的基礎類bean, 這些繼承的bean能夠在servlet特定的範圍內被覆蓋(應該是重寫的意思),你也能在給定的Servlet中本地定義一個新的特定範圍的bean

       

        在初始化DispatcherServlet時,SpringMVC在你的web應用中尋找WEB-INF目錄下的[servlet-name]-servlet.xml,並建立在這個檔案中定義的bean,在全域性範圍內覆蓋定義任何重名的bean定義。

       請考慮以下DispatcherServlet Servlet配置(在web.xml檔案中)

<web-app>
    <servlet>
        <servlet-name>golfing</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>golfing</servlet-name>
        <url-pattern>/golfing/*</url-pattern>
    </servlet-mapping>
</web-app>
上述的Servlet配置,你需要有一個名為/WEB-INF/golfing-servlet.xml的檔案在你的應用中。這個檔案包含你所有Spring Web MVC

具體的元件(bean)。 你可以通過Servlet初始化引數修改此配置檔案的具體位置

單個DispatcherServlet方案也有可能只有一個根上下文

這可以通過設定一個空的ContextConfigLocation servlet init引數進行配置,如下所示:

<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/root-context.xml</param-value>
    </context-param>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

  WebApplicationContext是作為對原生ApplicationContext的一個擴充套件,它具有web應用所需的一些額外的重要特性。它與普通的ApplicationContext不同之處在於它能解析主題, 並且它知道它與那個servlet相關聯(通過連線到ServletContext)。WebApplicationContext繫結在ServletContext中,如果你需要的話可以通過RequestContextUtils靜態類上的方法可以隨時查詢WebApplicationContext。

   請注意,我們可以用java程式碼實現同樣的配置

public class GolfingWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        // GolfingAppConfig defines beans that would be in root-context.xml
		//需要在root-context.xml中定義的bean
        return new Class[] { GolfingAppConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        // GolfingWebConfig defines beans that would be in golfing-servlet.xml
		 // GolfingWebConfig需要在golfing-servlet.xml定義的bean
        return new Class[] { GolfingWebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/golfing/*" };
    }

}

22.2.1 Special Bean Types In the WebApplicationContext


Spring框架的DispatcherServlet使用一些特殊的bean來處理request並呈現適當的檢視,這些bean是SpringMVC的一部分。你可以通過在WebApplicationContext簡單配置一個或者多個來使用這些bean. ,你並不需要初始化這些bean,如果你沒有配置任何內容也不要緊因為SpringMVC內部維護了一個預設的bean列表。更多的在下一節。 首先看下錶列出DispatcherServlet依賴的特殊bean型別。

Special bean types in the WebApplicationContext
根據一些標準將傳入的請求對映到處理程式和前處理程式和後處理程式列表(處理程式攔截器),其細節由HandlerMapping實現而異。 最流行的實現支援註釋控制器,但其他實現也存在。
HandlerAdapter 幫助DispatcherServlet呼叫對映到請求的處理程式,而不管實際呼叫哪個處理程式。 例如,呼叫帶註釋的控制器需要解析各種註釋。 因此,HandlerAdapter的主要目的是遮蔽DispatcherServlet和這些細節。
將基於邏輯字串的檢視名稱解析為實際的View型別。
解決您的Web應用程式可以使用的主題,例如,提供個性化的佈局
.儲存並檢索可以用於將屬性從一個請求傳遞到另一個請求的“輸入”和“輸出”FlashMap,通常是通過重定向。

Default DispatcherServlet Configuration

預設的DispatcherServlet配置

       在上一章節針對每一個特殊的bean所述,DispatcherServlet會維護預設使用的實現列表。此資訊儲存在包                                 org.springframework.web.servlet中的檔案DispatcherServlet.properties中。       

        所有的特殊bean都有一個合理的預設值,不久之後,您將需要自定義這些bean提供的一個或多個屬性。 例如,將InternalResourceViewResolver設定的字首屬性配置為檢視檔案的父位置是很常見的。

      無論細節如何,這裡要理解的重要概念是,一旦在WebApplicationContext中配置了一個特殊的bean,如InternalResourceViewResolver。您就有效地覆蓋了該特殊bean型別的預設實現列表。 例如,如果配置了InternalResourceViewResolver,則會忽略ViewResolver實現的預設列表。

      在第22.16節“配置Spring MVC”中,您將瞭解配置Spring MVC的其他選項,包括MVC Java配置和MVC XML名稱空間,這兩個名稱空間都提供了一個簡單的起點,並且對Spring MVC的工作原理幾乎不瞭解。 無論您如何選擇配置應用程式,本節中介紹的概念都是根本的,應該對您有所幫助。

DispatcherServlet Processing Sequence

      DispatcherServlet處理序列

      在您設定了DispatcherServlet之後,並且該特定DispatcherServlet啟動了一個請求,DispatcherServlet將按如下所示開始處理請求

       1. 在請求中搜索並繫結WebApplicationContext作為控制元件和程序中的其他元素可以使用的屬性。 預設情況下,它將在DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE鍵下繫結。

       2.語言環境解析器被繫結到請求,以使程序中的元素能夠解決在處理請求時使用的區域設定(渲染檢視,準備資料等)。 如果您不需要語言環境解析,則不需要它。

       3.主題解析器被繫結到使得諸如檢視之類的元素確定要使用哪個主題的請求。 如果不使用主題,可以忽略它。

       4.如果指定了多部分檔案解析器,則會檢查該請求的多部分; 如果找到多部分,則請求被包裝在MultipartHttpServletRequest中,以便程序中的其他元素進一步處理。 有關多部分處理的更多資訊,請參見第22.10節“Spring的多部分(檔案上傳)支援”。

       5.搜尋適當的處理程式。 如果找到處理程式,則執行與處理程式(預處理程式,後處理程式和控制器)關聯的執行鏈,以便準備模型或呈現

       6.如果返回模型,則呈現檢視。 如果沒有返回模型(可能是由於預處理程式或後處理程式攔截請求,可能是出於安全原因),則不會生成檢視,因為請求可能已經被滿足

        在WebApplicationContext中宣告的處理程式異常解析程式在處理請求期間提取異常。 使用這些異常解析器允許您定義自定義行為來解決異常。

        Spring DispatcherServlet還支援返回由Servlet API指定的最後修改日期。 確定特定請求的最後修改日期的過程很簡單:DispatcherServlet查詢適當的處理程式對映,並測試發現的處理程式是否實現了LastModified介面。 如果是,則LastModified介面的long getLastModified(request)方法的值將返回給客戶端。

         您可以通過將Servlet初始化引數(init-param元素)新增到web.xml檔案中的Servlet宣告來自定義單獨的DispatcherServlet例項。 有關支援的引數列表,請參見下表。

        DispatcherServlet初始化引數
引數 說明
contextClass 實現WebApplicationContext的類,它例項化了這個Servlet使用的上下文。 預設情況下,使用XmlWebApplicationContext。
contextConfigLocation 傳遞給上下文例項(由contextClass指定)以指示可以找到上下文的字串。 該字串可能包含多個字串(使用逗號作為分隔符)來支援多個上下文。 在具有兩次定義的bean的多個上下文位置的情況下,優先順序最高。
namespace WebApplicationContext的名稱空間。 預設為[servlet-name] -servlet。