本文首发于 2026 年 4 月 9 日,由 春风AI助手 整理出品,带你系统掌握 Spring Boot 内嵌 Tomcat 的核心原理、配置优化与面试考点。
一、开篇引入

Spring Boot 内嵌 Tomcat 是 Java 后端开发中绕不开的核心知识点——无论是日常开发还是大厂面试,它几乎都是必考题。但很多学习者的痛点恰恰在于:会启动项目、会写接口,却说不出 Tomcat 是怎么被“嵌”进去的;知道用了默认端口 8080,却回答不出内嵌与外部部署的本质区别;面试被问底层原理时,往往只能泛泛说“自动配置”,拿不到高分。春风AI助手 基于当前 Spring Boot 生态(3.x 主流 + 2026 年最新趋势),从问题出发,带你逐一拆解内嵌 Tomcat 的核心逻辑、源码流程、性能优化与高频考点,帮你建立完整知识链路。
二、痛点切入:为什么需要内嵌 Tomcat?

先看传统开发方式:过去开发一个 Web 应用,你需要先在机器上安装并配置外部 Tomcat,然后在 IDE 中配置部署路径,每次改完代码要重新打包部署,流程相当繁琐。外部 Tomcat 配置文件(如 server.xml)结构复杂,新手容易改错;环境不一致也容易引发“本地跑得好好的,部署就挂了”的问题。
下面是一段传统 JDK 原生实现 HTTP 服务的极简代码,可以帮我们理解底层本质:
// JDK 原生实现 HTTP 服务(不使用任何框架) public class MyServer { public static void main(String[] args) throws IOException { // 监听 8080 端口 HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0); // 创建处理器 HttpHandler handler = exchange -> { String response = "Hello, World!"; exchange.sendResponseHeaders(200, response.length()); exchange.getResponseBody().write(response.getBytes()); exchange.getResponseBody().close(); }; server.createContext("/", handler); server.start(); System.out.println("服务器启动成功,监听 8080 端口"); } }
这段代码虽然能跑,但缺点明显:要手动管理端口、手动解析 HTTP 协议、手动处理请求路由……每做一个接口都要重复大量底层逻辑,扩展性和开发效率极差-2。
Spring Boot 内嵌 Tomcat 正是为了解决这些痛点而生的设计选择:
简化部署:无需手动安装和配置外部 Tomcat,项目打包成
java -jar即可运行-59;开发体验提升:热启动、自动配置,改完代码马上生效;
版本自动管理:Spring Boot 自动管理 Tomcat 版本与框架的兼容性,避免手动匹配的麻烦-;
微服务友好:每个微服务自带独立运行环境,轻量级、易于容器化部署。
三、核心概念讲解:嵌入式 Tomcat(Embedded Tomcat)
嵌入式 Tomcat 是指将 Tomcat 服务器以 JAR 包依赖的形式嵌入到 Spring Boot 应用中,随应用一起启动和运行。
理解“嵌入式”可以用一个类比:传统方式像是去租一套精装房(外部 Tomcat),房东把一切都配好了,但你的东西搬进去要适应它的结构;嵌入式则像是买精装交付的商品房——所有配套设施(Tomcat)已经集成在房子里,你直接拎包入住,随时可以启动使用。
在 Spring Boot 中,只需在 pom.xml 中引入 spring-boot-starter-web 依赖,就自动引入 tomcat-embed-core、tomcat-embed-el 等嵌入式 Tomcat 核心组件-1-59:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- spring-boot-starter-web 会自动传递引入 spring-boot-starter-tomcat -->
嵌入式 Tomcat 的核心价值在于:让应用变成一个自包含的、可独立运行的服务单元,实现了真正的“一次构建,随处运行”。
四、关联概念讲解:外部 Tomcat(External Tomcat)
外部 Tomcat 是指在操作系统层面独立安装配置的 Tomcat 服务器,多个 Web 应用可以部署到同一个外部 Tomcat 实例上运行。
嵌入式 Tomcat 与外部 Tomcat 的关系可以这样理解:
嵌入式是“应用带着服务器跑”——应用是主体,Tomcat 是依附组件;
外部部署是“服务器带着应用跑”——Tomcat 是主体,应用是被部署单元。
两者的核心差异如下:
| 对比维度 | 嵌入式 Tomcat | 外部 Tomcat |
|---|---|---|
| 部署方式 | 一个 jar 包,java -jar 直接运行 | 需安装 Tomcat,打包成 war 部署 |
| 环境隔离 | 每个应用独立运行,互不影响 | 多个应用共享同一 Tomcat 进程 |
| 适用场景 | 微服务、云原生、DevOps 流水线 | 传统单体应用、多应用共用服务器 |
| 版本管理 | Spring Boot 自动管理版本兼容性 | 需手动维护 Tomcat 版本升级 |
| 资源占用 | 每个应用占用独立资源 | 共享 JVM,整体资源开销较小 |
一句话概括两者的逻辑关系:嵌入式是“自包含的独立执行单元”,外部部署是“托管到共享容器中”。
五、概念关系与区别总结
嵌入式与外部 Tomcat 并不是“谁好谁坏”的对立关系,而是在不同场景下的不同选择。核心原则是:
开发/测试/微服务场景 → 嵌入式,效率高、部署快;
传统生产环境/多应用共存 → 外部部署,资源复用、集中管理。
一句话记忆:嵌入式是“应用为王,Tomcat 陪跑”;外部部署是“容器为王,应用入驻”。
六、代码示例与执行流程演示
6.1 标准 Spring Boot 应用(使用内嵌 Tomcat)
@SpringBootApplication public class Application { public static void main(String[] args) { // 这行代码触发了整个容器的创建和启动 SpringApplication.run(Application.class, args); } } @RestController public class DemoController { @GetMapping("/hello") public String hello() { return "Hello, Spring Boot with Embedded Tomcat!"; } }
配置示例(application.yml) :
server: port: 8080 监听端口,可修改 tomcat: threads: max: 200 最大工作线程数(默认200) min-spare: 10 最小空闲线程数 accept-count: 100 请求队列大小 connection-timeout: 20000 连接超时时间(毫秒)
执行流程解读:
运行
main方法 → 触发SpringApplication.run();Spring Boot 根据 classpath 中的
spring-boot-starter-web判断当前为 Servlet Web 应用类型(WebApplicationType.SERVLET);自动装配过程中,
ServletWebServerFactoryAutoConfiguration检测到 Tomcat 类存在,创建TomcatServletWebServerFactory工厂-1;容器刷新时调用
onRefresh()钩子方法 →ServletWebServerApplicationContext获取工厂并调用getWebServer();Tomcat 实例创建 → 配置端口、线程池 → 启动 → 应用开始监听请求-1。
6.2 切换嵌入式容器(从 Tomcat 换成 Jetty)
如果想从默认的 Tomcat 换成轻量级的 Jetty,只需排除 Tomcat 依赖、添加 Jetty 依赖即可-13:
<dependencies> <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> </dependencies>
这种灵活替换能力正是 Spring Boot “自动配置”设计思想的体现——嵌入式容器被抽象为统一接口,切换时业务代码零改动-13。
七、底层原理与关键技术支撑
Spring Boot 内嵌 Tomcat 的实现主要依赖以下几个底层机制:
7.1 自动配置机制
spring.factories(Spring Boot 2.x)或 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Spring Boot 3.x)中注册了 ServletWebServerFactoryAutoConfiguration 自动配置类。当 classpath 中存在 Tomcat 相关类(如 Tomcat.class)时,条件注解 @ConditionalOnClass 会触发 Tomcat 容器的自动配置-1。
7.2 FactoryBean 工厂模式
TomcatServletWebServerFactory 实现了 FactoryBean 接口,作为工厂负责创建和配置 TomcatWebServer 实例,将 Tomcat 的复杂初始化过程封装在工厂内部。
7.3 生命周期同步
Spring 容器通过 ServletWebServerApplicationContext 管理 Tomcat 的生命周期:容器启动时创建并启动 Tomcat,容器关闭时调用 Tomcat.stop() 销毁容器-。
7.4 底层网络模型(NIO vs BIO)
Spring Boot 内嵌 Tomcat 默认使用 NIO(Non-blocking I/O) 模型,基于 Java NIO 的 Selector 机制,少量线程可处理大量并发连接,性能远优于传统的 BIO(Blocking I/O)模型-8。
7.5 2026 年最新趋势:虚拟线程(Virtual Threads)
Java 21 引入的虚拟线程(LTS 特性)是 2026 年性能优化的重要方向。虚拟线程本质是用户态的轻量级线程,与传统平台线程 1:1 映射操作系统线程不同,采用 M:N 映射模型。当虚拟线程执行 I/O 阻塞时,JVM 会自动挂起并释放载体线程,上下文切换成本趋零-51。
Spring Boot 3.2+ 配合 Java 21+ 可轻松开启 Tomcat 虚拟线程支持:
application.yml spring: threads: virtual: enabled: true
开启后,Tomcat 请求处理线程池将切换为虚拟线程模式,高并发场景下吞吐量显著提升-。
7.6 2026 年前沿:GraalVM 原生镜像
Spring Boot 内嵌 Tomcat 也可通过 GraalVM 编译为原生镜像,启动时间可从秒级优化至毫秒级,特别适合 Serverless 和边缘计算场景-。
八、高频面试题与参考答案
Q1:Spring Boot 默认使用哪个嵌入式服务器?为什么这么设计?
参考答案:默认使用 Apache Tomcat。设计原因:① Tomcat 是 Java 生态中最成熟稳定的 Servlet 容器;② Spring Boot 追求“开箱即用”,Tomcat 作为默认选择能覆盖绝大多数 Web 应用场景;③ 支持通过排除 spring-boot-starter-tomcat、添加 spring-boot-starter-jetty 或 spring-boot-starter-undertow 轻松切换-21。
Q2:Spring Boot 内嵌 Tomcat 的启动流程是怎样的?
参考答案:① 引入 spring-boot-starter-web 依赖;② 运行 main 方法触发 SpringApplication.run();③ 自动装配阶段,ServletWebServerFactoryAutoConfiguration 检测 Tomcat 类存在,创建 TomcatServletWebServerFactory 工厂;④ 容器刷新时调用 onRefresh() 钩子,通过工厂创建和启动 Tomcat 实例;⑤ Tomcat 绑定端口并开始监听请求-1。
Q3:嵌入式 Tomcat 和外部 Tomcat 部署有什么区别?
参考答案:核心区别在于部署模式与适用场景。嵌入式是将 Tomcat 作为依赖打包进应用,一个 jar 包直接运行,适合微服务和快速迭代;外部部署需要单独安装 Tomcat,将应用打包成 war 部署到容器中,适合传统单体或多应用共享服务器的场景。嵌入式版本由 Spring Boot 自动管理,避免了手动匹配兼容性问题-。
Q4:如何优化 Spring Boot 内嵌 Tomcat 的性能?
参考答案:常见优化手段包括:① 调整线程池参数(server.tomcat.threads.max、min-spare 等);② 启用 NIO 模型(现代版本默认已启用);③ 配置 JVM 内存参数(-Xms、-Xmx);④ 设置连接超时时间;⑤ Java 21+ 项目建议开启虚拟线程支持(spring.threads.virtual.enabled=true),高并发场景吞吐量可翻倍;⑥ 考虑切换为性能更优的 Undertow--。
Q5:Spring Boot 内嵌 Tomcat 默认的 I/O 模型是什么?
参考答案:默认使用 NIO(Non-blocking I/O),通过 NioEndpoint 实现,少量线程即可处理大量并发连接。老版本曾使用 BIO(Blocking I/O),但现代 Spring Boot 已全面切换到 NIO,这是 Spring Boot 能支持高并发的重要底层保障-8。
九、结尾总结
本文通过 春风AI助手 的系统梳理,完整覆盖了 Spring Boot 内嵌 Tomcat 的 四大核心模块:
概念定位:嵌入式 vs 外部部署的场景选择;
底层原理:自动配置机制 + FactoryBean 工厂模式 + 生命周期同步;
代码实践:基础配置 + 容器切换实战;
面试备考:5 道高频面试题标准答案 + 2026 年新趋势(虚拟线程、GraalVM)。
核心考点提示:面试中最容易被深挖的点在于“启动流程”和“I/O 模型”,建议结合源码级理解来准备。
下一篇预告:Spring Boot 内嵌 Tomcat 源码级深度剖析——从 SpringApplication.run() 到 Tomcat.start() 的全链路解析,敬请关注。