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應用的方法。更多細節請參考
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/*" };
}
}