Spring Boot启动流程解析及web.xml部署配置问题咨询
Spring Boot WAR包部署Tomcat的启动流程与web.xml配置问题
背景
之前了解了Spring的启动流程,但想明确Spring Boot在web.xml场景下的具体启动逻辑,同时遇到了配置问题,整理如下疑问:
核心疑问
- Spring Boot WAR包部署到Tomcat后,启动执行流程是怎样的?
- 包含main()方法的主类和继承SpringBootServletInitializer的类,哪个先执行?具体流程是怎样的?
web.xml配置问题
官方文档提到针对旧Servlet容器的web.xml场景,需要配置web.xml让DispatcherServlet加载Spring Boot的ApplicationContext,但我尝试的配置无法正常工作:
<servlet> <!-- Provide a Servlet Name --> <servlet-name>frontcontroller-dispatcher</servlet-name> <!-- Provide a fully qualified path to the DispatcherServlet class --> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <!-- Provide a Servlet Name that you want to map --> <servlet-name>frontcontroller-dispatcher</servlet-name> <!-- Provide a url pattern --> <url-pattern>/api/*</url-pattern> </servlet-mapping>
解答
1. WAR包部署到Tomcat的启动流程
当Spring Boot WAR包部署到Tomcat时,启动流程如下:
- Tomcat启动后,扫描部署的WAR包,优先解析
web.xml文件(传统web.xml场景不依赖Servlet 3.0的注解自动扫描) - 按照
web.xml中的配置顺序,依次初始化监听器、过滤器、Servlet - 核心是通过配置让Spring的上下文加载器(如
ContextLoaderListener)或DispatcherServlet加载Spring Boot的ApplicationContext,完成Spring容器初始化、Bean创建与注入,最终启动Web应用
2. main类与SpringBootServletInitializer的执行顺序
- 部署到Tomcat时,main()方法不会执行:main方法是Spring Boot Jar包自启动的入口,WAR包由Tomcat容器托管,容器不会调用main方法
- SpringBootServletInitializer子类的触发逻辑:默认Servlet 3.0+容器会自动扫描实现
WebApplicationInitializer的类(SpringBootServletInitializer实现了该接口),但如果是强制使用web.xml的旧容器,需要在web.xml中显式配置上下文加载逻辑。若同时存在web.xml和SpringBootServletInitializer,web.xml配置优先级更高,容器会先解析web.xml,再执行WebApplicationInitializer的逻辑
3. web.xml的正确配置方案
你之前的配置只定义了DispatcherServlet,但未指定它要加载的Spring Boot上下文,导致DispatcherServlet默认寻找/WEB-INF/frontcontroller-dispatcher-servlet.xml文件,而非你的Spring Boot注解配置类,因此无法正常初始化Spring容器。以下是正确配置:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!-- 配置Spring上下文监听器,加载根ApplicationContext --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 指定使用注解驱动的上下文,并指向你的Spring Boot主类 --> <context-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>com.example.YourSpringBootApplication</param-value> </context-param> <!-- 配置DispatcherServlet,复用根上下文避免重复加载 --> <servlet> <servlet-name>frontcontroller-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextAttribute</param-name> <param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>frontcontroller-dispatcher</servlet-name> <url-pattern>/api/*</url-pattern> </servlet-mapping> </web-app>
配置说明:
ContextLoaderListener:负责加载根Spring ApplicationContext,通过contextConfigLocation关联你的Spring Boot主类contextClass:指定使用AnnotationConfigWebApplicationContext,支持Spring Boot的@SpringBootApplication注解配置- DispatcherServlet的
contextAttribute参数:让DispatcherServlet复用根上下文,避免重复创建容器,保证Bean的单例性
内容的提问来源于stack exchange,提问作者skr
相关产品推荐
相关产品推荐

