Servlet3.0规范
Servlet3.0规范:Servlet容器(eg.Tomcat)启动后,会自动从容器中找ServletContainerInitializer
的实现类,然后通过反射创建实例并调用其onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
方法,传入两个参数,第一个为该实现类上的@HandlesTypes
注解指定的类型的所有后代类的集合,第二个为ServletContext
。
package javax.servlet;
public interface ServletContainerInitializer {
public void onStartup(Set<Class<?>> c, ServletContext ctx)
throws ServletException;
}
package javax.servlet.annotation;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface HandlesTypes {
Class<?>[] value();
}
SpringMVC接管Servlet容器
Spring提供了SpringServletContainerInitializer
实现了ServletContainerInitializer
接口,并指定对WebApplicationInitializer
接口的子类感兴趣
package org.springframework.web;
//SpringMVC接管Servlet容器(Tomcat),并指定对WebApplicationInitializer接口的子类感兴趣
@HandlesTypes(WebApplicationInitializer.class)
SpringServletContainerInitializer implements ServletContainerInitializer{
//Servlet容器启动后,会自动调这个方法,传入webAppInitializerClasses(感兴趣接口的后代类集合)和servletContext(servlet上下文)
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext){
//遍历传入的所有WebApplicationInitializer后代类,创建实例,并调用onStartup(servletContext)方法
......
}
}
public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerContextLoaderListener(servletContext);
}
protected void registerContextLoaderListener(ServletContext servletContext) {
//创建root的WebApplicationContext(父容器)
WebApplicationContext rootAppContext = createRootApplicationContext();
if (rootAppContext != null) {
//创建ContextLoaderListener,并监听rootAppContext的启动
ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
listener.setContextInitializers(getRootApplicationContextInitializers());
servletContext.addListener(listener);
}
else {
logger.debug("No ContextLoaderListener registered, as " +
"createRootApplicationContext() did not return an application context");
}
}
protected abstract WebApplicationContext createRootApplicationContext();
}
package org.springframework.web.servlet.support;
AbstractDispatcherServletInitialize extends AbstractContextLoaderInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
registerDispatcherServlet(servletContext);
}
//创建一个DispatcherServlet实例并添加到servletContext中
protected void registerDispatcherServlet(ServletContext servletContext){
String servletName = getServletName();
Assert.hasLength(servletName, "getServletName() must not return null or empty");
//创建Servlet的WebApplicationContext(子容器)
WebApplicationContext servletAppContext = createServletApplicationContext();
Assert.notNull(servletAppContext, "createServletApplicationContext() must not return null");
//创建DispatcherServlet
FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
Assert.notNull(dispatcherServlet, "createDispatcherServlet(WebApplicationContext) must not return null");
dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
//将创建的DispatcherServlet注册到创建的Servlet的WebApplicationContext中
ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
if (registration == null) {
throw new IllegalStateException("Failed to register servlet with name '" + servletName + "'. " +
"Check if there is another servlet registered under the same name.");
}
registration.setLoadOnStartup(1);
registration.addMapping(getServletMappings());
registration.setAsyncSupported(isAsyncSupported());
Filter[] filters = getServletFilters();
if (!ObjectUtils.isEmpty(filters)) {
for (Filter filter : filters) {
registerServletFilter(servletContext, filter);
}
}
customizeRegistration(registration);
}
protected abstract WebApplicationContext createServletApplicationContext();
protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
return new DispatcherServlet(servletAppContext);
}
}