<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.2.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.2.RELEASEversion>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.2version>
plugin>
plugins>
build>
Servlet3新规范:
Tomcat启动时会扫描classpath:META-INF.services.javax.servlet.ServletContainerInitializer文件
里面写的接口的所有实现类,执行onStartup()方法
注意:
@HandlesTypes注解的参数是一个接口,可以将他所有的实现类存到onStartup方法的参数Set> c中
这是由tomcat实现的
/**
* @author zc
* @version 1.0
* @date 2020/1/12 2:12 下午
* @desc
*/
@HandlesTypes(Test.class)
public class MyTestInit implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
System.out.println("===========mytest-------------");
for (Class<?> aClass : c) {
System.out.println(aClass);
}
}
}
/**
* @author zc
* @version 1.0
* @date 2020/1/12 2:20 下午
* @desc
*/
public interface Test {
}
/**
* @author zc
* @version 1.0
* @date 2020/1/12 2:24 下午
* @desc
*/
public class TestImpl implements Test {
}
javax.servlet.ServletContainerInitializer里面的内容
com.demo.MyTestInit
参考官方文档
实现WebApplicationInitializer这个接口就可以取代web.xml所做的事情
@Configuration
@ComponentScan("com.demo")
public class AppConfig {
}
/**
* @author zc
* @version 1.0
* @date 2020/1/12 1:04 下午
* @desc
*/
public class MyWebAppInit implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
System.out.println("+++++++++++++++++++++");
// Load Spring web application configuration
AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
ac.register(AppConfig.class);
ac.refresh();
// Create and register the DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(ac);
ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
registration.addMapping("/");
registration.setLoadOnStartup(1);
}
}
可以看看WebApplicationInitializer的源码
里面什么都没有
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;
}
参考servlet3新特性,来看看spring是怎么做的
找到如下文件
里面只有一行内容:org.springframework.web.SpringServletContainerInitializer
找到这个类
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
List<WebApplicationInitializer> initializers = new LinkedList<>();
if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// Be defensive: Some servlet containers provide us with invalid classes,
// no matter what @HandlesTypes says...
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer)
ReflectionUtils.accessibleConstructor(waiClass).newInstance());
}
catch (Throwable ex) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
}
}
}
}
if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
}
servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
这个注解上面讲了,可以将WebApplicationInitializer所有的实现类放到onStartup的入参中
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
他会循环执行WebApplicationInitializer所有实现类的onStartup()
而我们上面MyWebAppInit,就进行了spring环境的初始化