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 機制,是直接啟動的。

 


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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM