1: 原始的Spring mvc 项目是要使用web.xml 来把DispatchServlet注入到Tomcat中。

    2:Spring 3+后支持不使用xml配置,技术依赖Servlet3.0 SPI

    1. 新建Springmvc项目,引入依赖 ```xml org.springframework spring-webmvc 5.2.5.RELEASE
    org.apache.tomcat.embed tomcat-embed-core 8.5.43 org.apache.tomcat.embed tomcat-embed-jasper 8.5.34

    javax.servlet javax.servlet-api 4.0.0 provided

    1. 2. 添加启动配置类 AppConfig
    2. ```java
    3. @Configuration
    4. @ComponentScan("com.mkb")
    5. public class AppConfig {
    6. }
    1. 添加内置tomcat

      1. public class TomcatApplication {
      2. public static void run()throws Exception{
      3. /**
      4. * 这么启动tomcat不知道项目是web项目。所以不能执行MyWebApplicationInitializer 方法
      5. */
      6. Tomcat tomcat = new Tomcat();
      7. tomcat.setPort(8080);
      8. tomcat.addWebapp("/", "D:\\workspace\\webapp");
      9. tomcat.start();
      10. tomcat.getServer().await();
      11. }
      12. }
    2. 启动主函数

      1. public class MyWebApplicationInitializer implements WebApplicationInitializer {
      2. @Override
      3. public void onStartup(ServletContext servletCxt) {
      4. System.out.println("start");
      5. // Load Spring web application configuration
      6. AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
      7. ac.register(AppConfig.class);
      8. ac.refresh(); //初始化Spring容器
      9. // Create and register the DispatcherServlet
      10. DispatcherServlet servlet = new DispatcherServlet(ac);
      11. ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
      12. registration.setLoadOnStartup(1);
      13. registration.addMapping("/*");
      14. }
      15. }
    3. 测试

      1. @RestController
      2. public class IndexController {
      3. @RequestMapping("/test")
      4. public String index1(){
      5. return "1";
      6. }
      7. }

    总结:Spring 3.0后支持0配置,为后期springboot的演变做了铺垫。

    在Spring-web jar 下面, META-INF\services目录下会有一个javax.servlet.ServletContainerInitializer 类,按照SPI的规范,就是Tomcat的启动的时候 会加载这个目录下的这个配置。

    1. @HandlesTypes({WebApplicationInitializer.class})
    2. public class SpringServletContainerInitializer implements ServletContainerInitializer {
    3. public SpringServletContainerInitializer() {
    4. }
    5. public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
    6. List<WebApplicationInitializer> initializers = new LinkedList();
    7. Iterator var4;
    8. if (webAppInitializerClasses != null) {
    9. var4 = webAppInitializerClasses.iterator();
    10. while(var4.hasNext()) {
    11. Class<?> waiClass = (Class)var4.next();
    12. if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
    13. try {
    14. initializers.add((WebApplicationInitializer)ReflectionUtils.accessibleConstructor(waiClass, new Class[0]).newInstance());
    15. } catch (Throwable var7) {
    16. throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
    17. }
    18. }
    19. }
    20. }
    21. if (initializers.isEmpty()) {
    22. servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
    23. } else {
    24. servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
    25. AnnotationAwareOrderComparator.sort(initializers);
    26. var4 = initializers.iterator();
    27. while(var4.hasNext()) {
    28. WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
    29. initializer.onStartup(servletContext);
    30. }
    31. }
    32. }
    33. }

    @HandlesTypes({WebApplicationInitializer.class})
    就是说,凡是实现 WebApplicationInitializer 接口的类 都会被执行,我们的项目中 MyWebApplicationInitializer 实现了 WebApplicationInitializer 接口,所以在Tomcat启动的时候会加载MyWebApplicationInitializer,这个方法中,实现了Spring容器的初始化,和DispatcherServlet 的初始化。