本章內容java
This chapter covers Alternate Spring MVC configuration options Handling file uploads Handling exceptions in controllers Working with flash attributes
spring mvc的基本配置,以下示,在第5章第1節即5.1中
web
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected String[] getServletMappings() { return new String[] { "/" }; } @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[] { RootConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[] { WebConfig.class }; } }
需求:
spring
You may need servlets and filters in addition to DispatcherServlet. Maybe you need to do some additional configuration on DispatcherServlet itself. For pre-Servlet 3.0 container, you may need to configure DispatcherServlet in a traditional web.xml file.
7.1.1 Customizing DispatcherServlet configuration
數組
7.1.1 自定義DispatcherServlet配置mvc
代碼5.1(原文說的是代碼7.1,那是錯的.)中的三個方法,以下示,是在必須重寫的三個抽象方法.
app
getServletMappings getRootConfigClasses getServletConfigClasses
除此以外還有其它可選的重寫方法.如ide
customizeRegistration()
對象AbstractAnnotationConfigDispatcherServletInitializer在將DispatcherServlet註冊到servlet容器以後(在此過程當中還生成了ServletRegistration.Dynamic對象),會調用customizeRegistration()方法,把對象ServletRegistration.Dynamic傳遞給該方法.url
對象ServletRegistration.Dynamic是AbstractAnnotationConfigDispatcherServletInitializer在將DispatcherServlet註冊到servlet容器時生成的.經過重寫customizeRegistration()方法能夠將自定義的配置應用到DispatcherServlet中.spa
舉例說明,若是要啓用DispatcherServlet的multipart requests(相似上傳文件這樣的請求,能夠參考http://blog.csdn.net/five3/article/details/7181521),那麼須要重寫customizeRegistration方法並在方法內設置MultipartConfigElement對象,以下示
.net
@Override protected void customizeRegistration(Dynamic registration) { registration.setMultipartConfig( new MultipartConfigElement("/tmp/spittr/uploads")); }
這樣放到5.1裏就是這樣的,注意引入的包別引錯了.
import javax.servlet.MultipartConfigElement; import javax.servlet.ServletRegistration.Dynamic; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected String[] getServletMappings() { return new String[] { "/" }; } @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[] { RootConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[] { WebConfig.class }; } @Override protected void customizeRegistration(Dynamic registration) { registration.setMultipartConfig( new MultipartConfigElement("/tmp/spittr/uploads")); } }
在把ServletRegistration.Dynamic對象當參數傳遞給方法customizeRegistration()以後(其實就是重寫customizeRegistration這個方法以後),就能夠實現下面幾個功能了
1. set the load-on-startup priority by calling setLoadOnStartup()
2. set an initialization parameter by calling setInitParameter()
3. call setMultipartConfig() to configure Servlet 3.0 multipart support
7.1.2 Adding additional servlets and filters
7.1.2 配置servlet和過濾器
實現對象AbstractAnnotationConfigDispatcherServletInitializer的時候就建立了DispatcherServlet和ContextLoaderListener.可是若是要註冊別的servlets, filters, or listeners,如何操做?
使用java配置的一個好處就是定義的初始化類的數量能夠如你所願.所以,當須要註冊組件時,只須要建立一個初始化類便可.最簡單的方式 就是實現spring的WebApplicationInitializer接口.
下面的代碼顯示瞭如何經過實現WebApplicationInitializer接口來註冊一個servlet
import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration.Dynamic; import org.springframework.web.WebApplicationInitializer; public class MyServletInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { Dynamic myServlet = servletContext.addServlet("myServlet", MyServlet.class); myServlet.addMapping("/custom/**"); } }
上面的代碼是一個相對比較簡單的servlet註冊初始化類.該類註冊了一個servlet而後將其與單個路徑映射.其實DispatcherServlet也能夠經過這樣的方式來手動註冊,可是真的沒有必要,由於AbstractAnnotationConfigDispatcherServletInitializer已經替咱們作了不少工做.
相似地,也能夠經過建立一個WebApplicationInitializer實現來註冊監聽器或者過濾器,下面的代碼顯示瞭如何註冊一個過濾器
@Override public void onStartup(ServletContext servletContext) throws ServletException { javax.servlet.FilterRegistration.Dynamic filter = servletContext.addFilter("myFilter", MyFilter.class); filter.addMappingForUrlPatterns(null, false, "/custom/*"); }
在servlet3.0容器中,WebApplicationInitializer是一個通用的註冊servlets, filters, and listeners的方式.可是若是隻想要將註冊的過濾器與DispatcherServlet創建映射,在AbstractAnnotationConfigDispatcherServletInitializer中有快捷方式.
要註冊一個或者多個註冊器,並將其與DispatchServlet映射起來,只須要重寫getServletFilters() 方法便可.
@Override protected Filter[] getServletFilters() { return new Filter[] { new MyFilter() }; }
getServletFilters()這個方法在AbstractDispatcherServletInitializer中,而AbstractAnnotationConfigDispatcherServletInitializer又繼承自AbstractDispatcherServletInitializer,因此就在實現AbstractAnnotationConfigDispatcherServletInitializer時候重寫該方法便可.
import javax.servlet.Filter; import javax.servlet.MultipartConfigElement; import javax.servlet.ServletRegistration.Dynamic; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected String[] getServletMappings() { return new String[] { "/" }; } @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[] { RootConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[] { WebConfig.class }; } @Override protected void customizeRegistration(Dynamic registration) { registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads")); } @Override protected Filter[] getServletFilters() { return new Filter[] { new MyFilter() }; } }
觀察方法Filter[] getServletFilters(),可見該方法返回的是一個javax.servlet.Filter數組,上面的示例中,只返回了一個過濾器,但實際上能夠返回的過濾器數量如您所願.這裏沒有必要明確聲明將過濾器與DispatchServlet創建映射,由容器自動完成.
7.1.3 Declaring DispatcherServlet in web.xml
典型的建立DispatchServlet和ContextLoaderListener的xml配置
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/root-context.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
DispatchServlet和ContextLoaderListener會分別指定對應的應用上下文,上面的配置中,ContextLoaderListener指定了應用上下文,可是DispatchServlet沒有,這樣的話,默認使用的是應用名後接-context.xml的文件名的方式,該文件默認放在WEB-INF目錄下.
下面指定了DispatchServlet應用上下文
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/root-context.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring/appServlet/servlet-context.xml </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> </web-app>
下面的配置表示DispatcherServlet和ContextLoaderListener使用AnnotationConfigWebApplicationContext,該對象實現了WebApplicationContext,它會加載java配置類而不會加載xml文件.
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context.support.AnnotationConfigWebApplicationContext </param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>com.habuma.spitter.config.RootConfig</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context.support.AnnotationConfigWebApplicationContext </param-value> </init-param> <init-param> <param-name>contextConfigLocation</param-name> <param-value> com.habuma.spitter.config.WebConfigConfig </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>