1: 原始的Spring mvc 项目是要使用web.xml 来把DispatchServlet注入到Tomcat中。
2:Spring 3+后支持不使用xml配置,技术依赖Servlet3.0 SPI
- 新建Springmvc项目,引入依赖
```xml
org.springframework spring-webmvc 5.2.5.RELEASE
2. 添加启动配置类 AppConfig
```java
@Configuration
@ComponentScan("com.mkb")
public class AppConfig {
}
添加内置tomcat
public class TomcatApplication {
public static void run()throws Exception{
/**
* 这么启动tomcat不知道项目是web项目。所以不能执行MyWebApplicationInitializer 方法
*/
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);
tomcat.addWebapp("/", "D:\\workspace\\webapp");
tomcat.start();
tomcat.getServer().await();
}
}
启动主函数
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletCxt) {
System.out.println("start");
// Load Spring web application configuration
AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
ac.register(AppConfig.class);
ac.refresh(); //初始化Spring容器
// Create and register the DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(ac);
ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/*");
}
}
测试
@RestController
public class IndexController {
@RequestMapping("/test")
public String index1(){
return "1";
}
}
总结:Spring 3.0后支持0配置,为后期springboot的演变做了铺垫。
在Spring-web jar 下面, META-INF\services目录下会有一个javax.servlet.ServletContainerInitializer 类,按照SPI的规范,就是Tomcat的启动的时候 会加载这个目录下的这个配置。
@HandlesTypes({WebApplicationInitializer.class})
public class SpringServletContainerInitializer implements ServletContainerInitializer {
public SpringServletContainerInitializer() {
}
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
List<WebApplicationInitializer> initializers = new LinkedList();
Iterator var4;
if (webAppInitializerClasses != null) {
var4 = webAppInitializerClasses.iterator();
while(var4.hasNext()) {
Class<?> waiClass = (Class)var4.next();
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer)ReflectionUtils.accessibleConstructor(waiClass, new Class[0]).newInstance());
} catch (Throwable var7) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
}
}
}
}
if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
} else {
servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
var4 = initializers.iterator();
while(var4.hasNext()) {
WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
initializer.onStartup(servletContext);
}
}
}
}
@HandlesTypes({WebApplicationInitializer.class})
就是说,凡是实现 WebApplicationInitializer 接口的类 都会被执行,我们的项目中 MyWebApplicationInitializer 实现了 WebApplicationInitializer 接口,所以在Tomcat启动的时候会加载MyWebApplicationInitializer,这个方法中,实现了Spring容器的初始化,和DispatcherServlet 的初始化。