2026年4月深度解析:Spring Boot内嵌Tomcat原理与高频面试题全攻略

小编 2 0

在Java生态中,Spring Boot凭借“自动配置+内嵌容器”的设计理念,彻底改变了传统Web应用的开发与部署方式。而小孩ai助手作为学习资源,可以帮助开发者更系统地掌握这类核心知识点——本文将深入剖析Spring Boot默认内置的Tomcat嵌入式Web服务器的实现原理、配置实战与底层技术,帮你彻底打通从“会用”到“懂原理”的最后一公里。

很多Java开发者都会遇到这样的困境:日常开发中用Spring Boot跑接口顺风顺水,但一旦面试被问到“Spring Boot是怎么启动Tomcat的?”“内嵌Tomcat和外部Tomcat有什么本质区别?”等问题时就哑口无言。本文将聚焦这一问题,从传统部署痛点出发,全面拆解Spring Boot内嵌Tomcat的设计思想与底层机制,并附上代码示例和高频面试题。

📌 最新版本提示:截至2026年4月,Spring Boot最新稳定版为4.0.5(2026年3月26日发布),同时维护3.5.13版本,Tomcat 11.0.21已于2026年4月8日发布,实现了Jakarta EE 11平台规范。

一、痛点切入:传统Web开发为什么这么“重”?

传统做法:手动部署WAR到外部Tomcat

回忆一下传统的Java Web开发流程:

  1. 在IDE中编写Servlet/JSP代码

  2. 编译打包生成WAR文件

  3. 将WAR文件拷贝到Tomcat的webapps/目录

  4. 启动Tomcat服务器(或重启已运行的Tomcat)

  5. 通过浏览器访问 http://localhost:8080/your-app/...

对应的项目结构通常还需要配置复杂的web.xml文件:

xml
复制
下载
运行
<!-- 传统web.xml配置示例 -->
<web-app>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

传统方式的三宗罪

  • 耦合度高:开发和部署强依赖外部Tomcat环境,换个环境就要重新配置

  • 扩展性差:从单机到集群需要手动部署到每台机器的Tomcat,维护成本极高

  • 开发效率低:每次修改代码都需要重新打包→部署→重启,反馈周期长

这正是Spring Boot内嵌Tomcat要解决的核心痛点——让应用自己携带运行环境,实现“写完代码,直接运行”

二、核心概念讲解:什么是嵌入式Web服务器?

概念A:嵌入式Web服务器(Embedded Web Server)

定义:嵌入式Web服务器是指将Web容器的代码以依赖库的形式打包进应用程序中,应用启动时直接在JVM进程中创建并启动Web服务,无需外部独立部署。

关键词拆解

  • 嵌入式:不是独立的进程,而是应用程序的一部分

  • Web服务器:负责接收HTTP请求、调用业务逻辑、返回响应

  • 一体化:应用JAR包 = 业务代码 + Web服务器 + 依赖环境

生活化类比:把传统方式想象成“要去饭店吃饭”——你需要先到饭店(启动Tomcat),然后再点菜(部署WAR)。而内嵌方式就像“叫外卖送到家”——饭菜和配送服务是一个整体,一次性交付。

概念B:Servlet容器

定义:Servlet容器是实现Jakarta Servlet规范(原Java Servlet规范)的Web服务器组件,负责管理Servlet的生命周期、处理HTTP请求映射、维护会话等。

与概念A的关系:Tomcat既是一个Servlet容器,也是Spring Boot默认的嵌入式Web服务器。嵌入式Web服务器是一种设计理念,而Servlet容器是这个理念的具体实现载体

Tomcat 11版本速览(2026年4月最新)-22-21

版本实现规范JDK要求核心变化
Tomcat 9.xJava EE 8JDK 8+传统javax.包,2027年3月结束支持
Tomcat 10.xJakarta EE 9/10JDK 8/11+包名从javax.改为jakarta.
Tomcat 11.xJakarta EE 11JDK 17+支持Servlet 6.0、Pages 4.0规范

⚠️ 重要提醒:从Tomcat 9升级到10/11时,API包名从javax.变更为jakarta.,代码需要适配修改,官方提供了迁移工具辅助升级。-22

三、概念关系与区别总结

嵌入式Web服务器 vs Servlet容器 vs Tomcat

概念层级具体内容一句话定位
设计思想嵌入式Web服务器应用自带运行环境,无需外部部署
实现载体Servlet容器管理Servlet生命周期,处理HTTP请求映射
具体产品Apache Tomcat集以上两者于一身的开源实现

一句话记忆:Spring Boot用嵌入式的思想,通过Servlet容器规范,借助Tomcat这个具体产品,实现了“一行命令跑起整个Web应用”。

四、代码/流程示例演示

最简单的Spring Boot + 内嵌Tomcat示例

第一步:添加Maven依赖

xml
复制
下载
运行
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>4.0.5</version>   <!-- 2026年3月最新稳定版 -->
</parent>

<dependencies>
    <!-- 引入spring-boot-starter-web,自动传递引入内嵌Tomcat -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

💡 spring-boot-starter-web 会自动引入 spring-boot-starter-tomcat,其中包含了 tomcat-embed-core 等核心依赖。-70

第二步:编写启动类和Controller

java
复制
下载
@SpringBootApplication  // 核心注解:组合了@Configuration + @EnableAutoConfiguration + @ComponentScan
public class Application {
    public static void main(String[] args) {
        // 关键入口:触发整个启动流程,包括内嵌Tomcat的创建与启动
        SpringApplication.run(Application.class, args);
    }
}

@RestController
public class DemoController {
    @GetMapping("/hello")
    public String hello() {
        return "Hello, Embedded Tomcat!";
    }
}

第三步:一键运行

bash
复制
下载
mvn spring-boot:run
 或打包后直接运行
mvn clean package
java -jar target/demo-1.0.jar

访问 http://localhost:8080/hello,即可看到返回结果。整个过程中,无需安装、配置或启动任何外部Tomcat。

自定义Tomcat配置(application.yml)

yaml
复制
下载
server:
  port: 9090                      修改端口
  tomcat:
    threads:
      max: 200                    最大工作线程数(默认200)
      min-spare: 10               最小空闲线程数(默认10)
    accept-count: 100             等待队列长度(默认100)
    connection-timeout: 20000     连接超时时间(毫秒)

替换内嵌Web容器(Tomcat → Jetty)

xml
复制
下载
运行
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

📊 选择参考:Tomcat生态最完善、文档最丰富,适合绝大多数场景;Jetty更轻量、启动更快,适合微服务网关;Undertow并发性能更优,适合高吞吐量场景。-

五、底层原理/技术支撑

Spring Boot启动时内嵌Tomcat的创建与启动,核心依赖以下几个技术点:

核心流程

图表
代码
下载
全屏
.kvfysmfp{overflow:hidden;touch-action:none}.ufhsfnkm{transform-origin: 0 0}
mermaid-svg-10{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}mermaid-svg-10 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}mermaid-svg-10 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}mermaid-svg-10 .error-icon{fill:552222;}mermaid-svg-10 .error-text{fill:552222;stroke:552222;}mermaid-svg-10 .edge-thickness-normal{stroke-width:1px;}mermaid-svg-10 .edge-thickness-thick{stroke-width:3.5px;}mermaid-svg-10 .edge-pattern-solid{stroke-dasharray:0;}mermaid-svg-10 .edge-thickness-invisible{stroke-width:0;fill:none;}mermaid-svg-10 .edge-pattern-dashed{stroke-dasharray:3;}mermaid-svg-10 .edge-pattern-dotted{stroke-dasharray:2;}mermaid-svg-10 .marker{fill:333333;stroke:333333;}mermaid-svg-10 .marker.cross{stroke:333333;}mermaid-svg-10 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}mermaid-svg-10 p{margin:0;}mermaid-svg-10 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:333;}mermaid-svg-10 .cluster-label text{fill:333;}mermaid-svg-10 .cluster-label span{color:333;}mermaid-svg-10 .cluster-label span p{background-color:transparent;}mermaid-svg-10 .label text,mermaid-svg-10 span{fill:333;color:333;}mermaid-svg-10 .node rect,mermaid-svg-10 .node circle,mermaid-svg-10 .node ellipse,mermaid-svg-10 .node polygon,mermaid-svg-10 .node path{fill:ECECFF;stroke:9370DB;stroke-width:1px;}mermaid-svg-10 .rough-node .label text,mermaid-svg-10 .node .label text,mermaid-svg-10 .image-shape .label,mermaid-svg-10 .icon-shape .label{text-anchor:middle;}mermaid-svg-10 .node .katex path{fill:000;stroke:000;stroke-width:1px;}mermaid-svg-10 .rough-node .label,mermaid-svg-10 .node .label,mermaid-svg-10 .image-shape .label,mermaid-svg-10 .icon-shape .label{text-align:center;}mermaid-svg-10 .node.clickable{cursor:pointer;}mermaid-svg-10 .root .anchor path{fill:333333!important;stroke-width:0;stroke:333333;}mermaid-svg-10 .arrowheadPath{fill:333333;}mermaid-svg-10 .edgePath .path{stroke:333333;stroke-width:2.0px;}mermaid-svg-10 .flowchart-link{stroke:333333;fill:none;}mermaid-svg-10 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}mermaid-svg-10 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}mermaid-svg-10 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}mermaid-svg-10 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}mermaid-svg-10 .cluster rect{fill:ffffde;stroke:aaaa33;stroke-width:1px;}mermaid-svg-10 .cluster text{fill:333;}mermaid-svg-10 .cluster span{color:333;}mermaid-svg-10 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid aaaa33;border-radius:2px;pointer-events:none;z-index:100;}mermaid-svg-10 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:333;}mermaid-svg-10 rect.text{fill:none;stroke-width:0;}mermaid-svg-10 .icon-shape,mermaid-svg-10 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}mermaid-svg-10 .icon-shape p,mermaid-svg-10 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}mermaid-svg-10 .icon-shape rect,mermaid-svg-10 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}mermaid-svg-10 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}mermaid-svg-10 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}mermaid-svg-10 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

SpringApplication.run

refreshContext
刷新IOC容器

onRefresh钩子
模板方法模式

ServletWebServerApplicationContext
创建WebServer

TomcatServletWebServerFactory.getWebServer

创建Tomcat实例
设置端口/Connector/Context

Tomcat.start
启动内嵌服务器

关键代码路径-40

  1. @SpringBootApplication 中的 @EnableAutoConfiguration 触发自动配置扫描

  2. 扫描 META-INF/spring.factories,加载 ServletWebServerFactoryAutoConfiguration

  3. 该配置类根据classpath中的依赖,实例化 TomcatServletWebServerFactory

  4. Spring容器刷新(refreshContext)过程中,onRefresh() 钩子调用 ServletWebServerApplicationContext.createWebServer()

  5. 调用 TomcatServletWebServerFactory.getWebServer() 完成Tomcat的创建、配置和启动

底层依赖的技术基础

  • 反射:Spring通过反射机制动态加载和实例化Tomcat相关类

  • SPI机制spring.factories 本质是Java SPI思想的扩展实现

  • 模板方法模式AbstractApplicationContext.onRefresh() 定义了扩展点,让子类实现具体逻辑

  • 事件/监听器:Spring通过ApplicationEvent和ApplicationListener实现容器生命周期与Tomcat生命周期的同步管理

💡 进阶提示:内嵌Tomcat的本质是在JVM进程中内嵌启动一个Servlet容器实例,这与传统独立Tomcat进程接收请求的架构有本质区别,但对上层的Servlet规范开发者来说是透明的。

六、高频面试题与参考答案

面试题1:Spring Boot 默认使用什么嵌入式Web容器?如何替换?

参考答案

  • Spring Boot默认使用 Apache Tomcat 作为嵌入式Web容器

  • 替换方法:在 pom.xml 中排除 spring-boot-starter-tomcat,引入 spring-boot-starter-jettyspring-boot-starter-undertow-49-70

  • 踩分点:Tomcat → Jetty/Undertow;通过starter机制自动装配

面试题2:Spring Boot 内嵌 Tomcat 的启动流程是怎样的?

参考答案(层次化记忆):

  1. 入口层SpringApplication.run() 启动Spring容器

  2. 刷新层refreshContext() 触发容器刷新

  3. 钩子层onRefresh() 模板方法触发WebServer创建

  4. 工厂层TomcatServletWebServerFactory.getWebServer() 创建Tomcat实例

  5. 启动层:调用Tomcat的 start() 方法完成内嵌服务器启动-40

  • 踩分点:按“入口→刷新→钩子→工厂→启动”五层递进回答,逻辑清晰

面试题3:内嵌Tomcat和外部独立Tomcat有什么区别?

对比维度内嵌Tomcat外部独立Tomcat
部署方式java -jar app.jar 一键运行需安装Tomcat,手动部署WAR
配置方式application.yml 或代码配置server.xml / context.xml
环境隔离每个应用独立的JVM进程多应用共享Tomcat进程
适用场景微服务、云原生、开发测试传统单体应用、多应用共用服务器

踩分点:从部署方式、配置方式、环境隔离、适用场景四个维度对比回答

面试题4:Spring Boot 如何实现“约定大于配置”来内嵌Web容器?

参考答案

  • spring-boot-starter-web 自动引入Tomcat依赖,无需手动配置

  • @EnableAutoConfiguration + spring.factories 自动加载 ServletWebServerFactoryAutoConfiguration

  • ServerProperties 自动绑定 application.yml 中的配置

  • 一句话总结:通过依赖即配置 + 自动配置类扫描 + 属性绑定,实现了“引入依赖即拥有内嵌容器”的效果

  • 踩分点:starter机制、自动配置类、属性绑定三者联动

七、总结

核心知识点回顾

  1. 什么是内嵌Web服务器:应用自带Web容器,无需外部部署

  2. Tomcat的双重身份:既是Servlet容器,也是嵌入式Web服务器的具体实现

  3. 启动流程:Spring容器刷新 → onRefresh钩子 → WebServerFactory → Tomcat实例化与启动

  4. 底层支撑:反射、SPI机制、模板方法模式、事件监听

  5. 配置与替换application.yml 灵活配置,starter机制支持无缝切换Jetty/Undertow

易错点提醒

  • ❌ 不要手动 new Tomcat() —— 会绕过Spring的自动配置,失去AOP、事务等核心能力-70

  • ❌ 内嵌模式下没有 conf/server.xml 文件,配置全部通过YAML或Java完成-70

  • ❌ 内嵌Tomcat不需要(也没有)webapps 目录,静态资源放在 src/main/resources/static/

进阶方向预告

下一篇将深入 Spring Boot WebFlux 响应式编程,讲解如何基于Netty实现非阻塞I/O,对比传统Servlet容器的线程模型差异,敬请期待。