• 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

  • 相关阅读:
    android之sharedpreference的两种使用方法
    andoird软件开发之一个记录账号密码的APP--bmob后台
    Android群英传笔记系列三 view的自定义:实现一个模拟下载
    android之文件操作——读取assets和raw文件下的内容
    fragment与viewPaper的使用
    Android之静态和动态加载Fragment
    Swift可选类型
    swift中的类型转化
    SDAutoLayerOut
    github 使用教程
  • 原文地址:https://www.cnblogs.com/jhxxb/p/13596565.html
Copyright © 2020-2023  润新知