1. 程式人生 > >22 Web MVC framework( 2. The DispatcherServlet)

22 Web MVC framework( 2. The DispatcherServlet)

Spring的web MVC框架 就像許多其他的web MVC框架一樣,請求驅動,圍繞著一箇中央Servlet來設計,而這個Servlet把請求分發給控制器,並且提供其他的功能來幫助web應用的開發。Spring的DispatcherServlet 不管怎麼樣,都比這個做的多。它是和Spring的Ioc容器完全整合,並且允許你使用Spring提供的其他任何特性。 Spring Web MVC 的DIspatcherServlet的請求處理工作流由下面的插圖來說明。pattern-savvy reader將識別出DispatcherServlet是一個前端控制器(Front Controller)設計模式的語法(這是一個Spring Web MVC和其他主流web框架共享的模式)。 在這裡插入圖片描述

DispatcherServlet是一個實時的Servlet(它繼承自HttpServlet基類),並且在你的Web應用中宣告。你需要把請求對映到你想讓其處理的DispatcherServlet上,通過使用一個URL對映。這是一個在Servlet3.0以上的環境中的標準JavaEE Servlet配置。

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是一個由Spring MVC提供的藉口,用來確保你基於程式碼的配置可以被檢測到,並且被自動呼叫來初始化任何Servlet3容器。一個實現了名為【AbstractAnnotationConfigDispatcherServletInitializer】介面的抽象基類甚至可以更簡單的註冊DispatcherServlet,通過簡單指定它的servlet對映和列表配置類–這甚至是一個被推薦的用來建立你的SpringMVC應用的方法。更多細節請參考

Code-based Servlet container initialization

DispatcherServlet是一個實時Servlet(它繼承自HttpServlet基類),並且在你的web應用的web.xml中宣告。你需要把請求對映到你想讓其處理的DispatcherServlet上,通過使用在同一個web.xml檔案中的URL對映。在下面的例子中,這是一個標準Java EE Servlet配置,演示了一個DispatcherServlet的宣告和對映。 下面是web.xml,等價於上面的例子中的程式碼

<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>

就像在Section 7.15, “Additional Capabilities of the ApplicationContext”,描述的,在Spring中的ApplicationContext例項可以被確定範圍的。在Web MVC 框架中,每一個DispatcherServlet都有它自己的WebApplicationContext,繼承了所有已經在根WebApplicationContext中定義的bean。根WebApplicationContext應該包含所有當前context與你的其他context和Servlet例項間進行共享的基礎bean。這些被繼承的bean可以在特定的Servlet範圍內被過載,並且你可以定義新的特定範圍的bean給一個指定的Servlet例項。 在這裡插入圖片描述

在一個DispatcherServlet初始化時,Spring MVC會在你的web應用的WEB-INF資料夾裡找名為【servlet-name】-servlet.xml的檔案,並且建立在那裡定義的bean,過載在全域性域中用相同名字命名的bean的定義。

考慮下面的DispatcherServlet定義(在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特性元件(beans)。你可以修改這個配置檔案的精確的位置通過一個Servlet初期化引數(細節參照下面)。 單獨一個DispatcherServlet的情況下,只擁有一個root context也是可能的。 在這裡插入圖片描述

也可以通過設定一個空的contextConfilLocation servlet初期化引數來配置,就像下面所演示的

<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不同的是,它是可以解析主題(參考Section 22.9, “Using themes”),並且可以知道他所連線的Servlet(通過一個到ServletContext的link)。WebApplicationContext被限制在ServletContext上,並且通過使用RequestContextUtils的靜態方法類你可以在你需要訪問的時候找到WebApplicationContext.

請注意我們通過基於JAVA的配置也可以實現相同的事情

public class GolfingWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        // GolfingAppConfig defines beans that would be in root-context.xml
        return new Class[] { GolfingAppConfig.class };
    }

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

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

}