1. 程式人生 > 實用技巧 >SpringBoot 使用外部 Tomcat 容器執行

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