• SpringBoot 使用外部 Tomcat 容器运行


    继承 SpringBootServletInitializer  类,重写 configure 方法

    @SpringBootApplication
    public class SpisApplication extends SpringBootServletInitializer {
    
        public static void main(String[] args) {
            SpringApplication.run(SpisApplication.class, args);
        }
    
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
            return builder.sources(SpisApplication.class);
        }
    }

    原理

    servlet 部分

    从 servlet 3.0 开始,Tomcat 启动时会自动加载实现了 ServletContainerInitializer  接口的类(需要在 META-INF/services 目录下新建配置文件)。也称为 SPI 机制

    package javax.servlet;
    
    import java.util.Set;
    
    public interface ServletContainerInitializer {
        public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException; 
    }

    spring 部分

    SpringServletContainerInitializer 的 onStartup 会被执行,webAppInitializerClasses 参数是所有实现了 WebApplicationInitializer 接口的类(servlet 注解 @HandlesTypes(WebApplicationInitializer.class) 的作用)

    package org.springframework.web;
    
    import java.lang.reflect.Modifier;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.ServiceLoader;
    import java.util.Set;
    
    import javax.servlet.ServletContainerInitializer;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.HandlesTypes;
    
    import org.springframework.core.annotation.AnnotationAwareOrderComparator;
    import org.springframework.lang.Nullable;
    import org.springframework.util.ReflectionUtils;
    
    @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) { 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); } } }

    再看 SpringBoot 启动类所需要继承的类

    public abstract class SpringBootServletInitializer implements WebApplicationInitializer

    就是这个接口,所以 Tomcat 启动时 SpringBoot 也就跟着启动了

    public interface WebApplicationInitializer {
        void onStartup(ServletContext servletContext) throws ServletException;
    }

    附上利用 Servlet 该特性的 SSM 整合:https://www.cnblogs.com/jhxxb/p/10512553.html

    SpringBoot 内嵌 Tomcat 的启动不是 SPI 机制,是直接启动的,可以参看这里的内嵌 Tomcat 启动类:https://www.cnblogs.com/jhxxb/p/13564329.html


    https://spring.io/blog/2014/03/07/deploying-spring-boot-applications

    https://blog.csdn.net/f641385712/article/details/87474907

  • 相关阅读:
    如何多个router 进行合并?
    钉钉微应用开发
    vscode 常用命令行
    window.location.search 为何在url 带# 号时获取不到 ?
    如何在嵌套的app中运用vue去写单页面H5
    两秒内不能重复点击
    linux系统下安装dubbo-admin
    二、SpringBoot实现上传文件到fastDFS文件服务器
    一、手把手教你docker搭建fastDFS文件上传下载服务器
    idea中git远程版本回退
  • 原文地址:https://www.cnblogs.com/jhxxb/p/13596565.html
Copyright © 2020-2023  润新知