WebApplicationInitializer
spring-web:
org.springframework.web.WebApplicaitonInitializer
public interface WebApplicationInitializer {
/**
* Configure the given {@link ServletContext} with any servlets, filters, listeners
* context-params and attributes necessary for initializing this web application. See
* examples {@linkplain WebApplicationInitializer above}.
* @param servletContext the {@code ServletContext} to initialize
* @throws ServletException if any call against the given {@code ServletContext}
* throws a {@code ServletException}
*/
void onStartup(ServletContext servletContext) throws ServletException;
}
目的
Servlet 3.0+
之后,为了替换web.xml这种配置方式,采用编码的方式来定义ServletContext.
比如添加servlet、filter、listener
原理
在Servlet 3.0+的容器中,有一个类SpringServletContainerInitializer
,在容器启动的时候,会去加载所有实现了WebApplicaitonInitializer
接口的实例(抽象类是不会被执行的),然后执行它的启动方法。
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
与web.xml对比
在web.xml中定义一个 Servlet
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/dispatcher-config.xml</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>}
使用WebApplicationInitailizer接口
使用spring的xml配置方式
public class MyWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher", new DispatcherServlet(appContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
完全不使用xml
采用@Configuration注解和AnnotationConfigWebApplicationContext类。
AnnotationConfigWebApplicationContext 用来创建Root Context,然后在Root Context中添加Servlet Context。
public class MyWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext =
new AnnotationConfigWebApplicationContext();
//AppConfig.class是一个用@Configuration注解的类
rootContext.register(AppConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext =
new AnnotationConfigWebApplicationContext();
//DispatcherConfig.class是一个用@Configuration注解的类
dispatcherContext.register(DispatcherConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
顺序性的考虑
设计上可以通过@Order或者实现Order接口来处理。但是在项目中我们一般不这么用。
为什么呢?
因为我们容器的初始化工作全部集中在一个WebApplicationInitializer
中完成。
与web.xml的兼容性
这里是可以同时使用的
但是要注意web.xml的版本必须是3.0+
同时WebApplicationInitializer
是可以修改web.xml中定义的内容。
问题
在tomcat 7.0.14以前,DefaultServlet的默认匹配路径是“/”,在WebApplicationInitializer
中是无法修改的。之后的版本可以做到覆盖。