前言
Spring Boot 的目标是构建“非常容易创建、独立、产品级别的基于Spring的应用”。这些应用是“立即可运行的”。在这个过程中,完全没有代码生成,不需要配置任何特殊的XML配置,为了这个目标,Spring Boot 在 Spring 4.0 框架之上提供了很多特性,帮助应用以“约定优于配置”“开箱即用”的方式来启动应用并运行上下文。
Spring Boot 同样改变了一个传统的 Web 应用服务的启动流程和部署方式。通过自动配置机制,Spring Boot 提供了一个嵌入式的运行时容器环境,并使用代码注解的方式在代码中将 URL 服务地址映射到 Controller 的方法完成服务映射。
所以,开发者不再需要关心传统容器(如
Tomcat)中web.xml
的配置,同时实现容器的具体技术都是可替换及可更改的,这些技术以插件化的Starter组件方式在运行时加载到
Spring 容器中。

什么是嵌入式容器
嵌入式容器是指将Servlet容器(如Tomcat、Jetty、Undertow)直接集成到应用程序中,而不是作为独立的外部服务器运行。这种设计使得应用程序可以作为一个独立的单元运行,无需额外安装和配置Web服务器。
优势:
- 简化部署:应用程序打包为可执行的JAR文件,包含所有依赖和运行时环境,部署时只需运行JAR文件即可。
- 开发便捷:无需配置外部服务器,开发者可以专注于业务逻辑,快速启动和测试应用。
- 灵活性:支持多种容器(Tomcat、Jetty、Undertow),开发者可以根据需求自由切换。
- 适合云原生:嵌入式容器轻量且易于扩展,非常适合微服务和云原生应用场景。
Servlet 容器:管理、运⾏ Servlet 组件(Servlet、Filter、Listener)的环境,⼀般指服务器。
Spring Boot默认使用Tomcat作为嵌入式Servlet容器,但也支持Jetty和Undertow。开发者可以通过简单的依赖配置切换容器。
其对应的 Java Web 容器发展至今也分为 Servlet Web
容器和
Reactive Web
容器,前者的使用率大概占比是百分之九十左右,其具体的实现有
Tomcat
、Jetty
和
Undertow
;而后者它的默认实现为
Netty Web Server
Servlet 规范是 Java Web 开发的核心标准,由 Java Community Process(JCP)制定,用于定义 Web 容器与 Servlet 组件之间的交互规则。以下是 Tomcat、Jetty、Undertow 对 Servlet 规范的兼容情况对比:
容器名称 | 最新稳定版本 | 支持的最高 Servlet 规范 | 关键特性 |
---|---|---|---|
Tomcat | 10.1.x(2023 年) | Servlet 5.0(JSP 3.0) | - 最广泛使用的 Java Web 容器 - 轻量级、高稳定性 - 完整支持 JSP 与 EL 表达式 - 适用于中小型企业应用 |
Jetty | 12.0.x(2023 年) | Servlet 5.0(WebSocket 2.0) | - 高性能异步处理能力 - 支持嵌入式部署(如 Spring Boot) - 轻量级架构,启动速度快 - 对 WebSocket 支持尤为出色 |
Undertow | 2.3.x(2023 年) | Servlet 4.0(WebSockets 1.1) | - Red Hat 开发的高性能容器 - 基于 NIO 的非阻塞模型 - 内存占用低,适合微服务场景 - 与 Spring Boot 默认集成度高 |
其中的容器如何选择:
- Tomcat:兼容性优先
- 若应用依赖 JSP 或需要兼容旧版框架(如 Struts 2),Tomcat 是首选。
- Spring Boot 默认使用 Tomcat,适合快速搭建传统 Web 应用。
- Jetty:异步与 WebSocket 场景
- 实时通信系统(如在线聊天、股票行情)推荐 Jetty,其 WebSocket 性能优于 Tomcat。
- 嵌入式服务(如工具类应用)因轻量级特性更适合 Jetty。
- Undertow:高性能与微服务
- 高并发、低延迟场景(如 API 网关、实时数据处理)优先选择 Undertow。
- 与 Spring Boot 集成时,可通过配置
application.properties
切换:
自动配置嵌入式容器的原理
核心机制
Spring Boot 自动配置嵌入式容器的核心是通过 条件注解 和 工厂模式 实现的。这一机制遵循 “约定优于配置” 的原则,使开发者无需手动配置服务器。
关键组件:
ServletWebServerFactoryAutoConfiguration
:主配置类,负责检测环境并加载合适的容器配置ServletWebServerFactory
:工厂接口,负责创建具体的 Web 服务器实例WebServer
:抽象接口,代表实际运行的 Web 服务器(如 Tomcat、Jetty)ServerProperties
:配置属性类,绑定application.properties
中的server.*
配置EmbeddedWebServerFactoryCustomizerAutoConfiguration
:
条件注解的作用:
@ConditionalOnClass
:确保类路径中存在指定类时才生效@ConditionalOnWebApplication
:确保应用是 Web 应用时才生效@ConditionalOnMissingBean
:确保容器中不存在指定 Bean 时才创建
工作流程
其中 Spring Boot 自动配置嵌入式 Servlet 容器的核心类是
ServletWebServerFactoryAutoConfiguration
,从其源码我们能得知
ServletWebServerFactoryAutoConfiguration 分析
1 | // 是一个配置类,定义Spring Bean。 |
这个配置类的主要功能:
- 通过
@Import
导入三种容器的配置类,但只会根据类路径中存在的依赖激活其中一个 @EnableConfigurationProperties
绑定ServerProperties
,使application.properties
中的配置生效,这些属性会在自动配置阶段被注入到嵌入式容器的工厂类(如TomcatServletWebServerFactory
)中。@AutoConfigureOrder
确保该配置类优先加载
源码分析:
ServletWebServerFactoryAutoConfiguration
⾃动配置了嵌⼊式容器场景,ServerProperties
类通过@ConfigurationProperties
注解绑定配置文件中的属性,这些属性会被注入到工厂类中,影响服务器的行为绑定了
ServerProperties
配置类,所有和(嵌入式容器)服务器有关的配置都在以server
开头的配置tomcat
调优就在server-tomcat
所有配置
ServletWebServerFactoryAutoConfiguration
导入了嵌入式的三大服务器Tomcat
、Jetty
、Undertow
导⼊
Tomcat
、Jetty
、Undertow
都有条件注解。系统中有这个类才行(也就是导了包)默认
Tomcat
配置⽣效。给容器中放TomcatServletWebServerFactory
都给容器中
ServletWebServerFactory
放了⼀个 web服务器工厂(造web服务器的)web服务器工厂 都有⼀个功能,
getWebServer
获取web服务器1
2
3
4
5
6
7public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
Tomcat tomcat = new Tomcat();
File baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat");TomcatServletWebServerFactory
创建了 tomcat。
ServletWebServerFactory
什么时候会创建 webServer 出来,ServletWebServerApplicationContext
,ioc容器,启动的时候会调⽤创建 web 服务器Spring 容器刷新的时候,会预留一个时机,刷新子容器,
onRefresh()
,而所谓容器刷新,就是容器启动refresh()
容器刷新十二大步的刷新⼦容器会调用,onRefresh()
,而在onRefresh()
方法中,ServletWebServerApplicationContext
会调用createWebServer()
方法
1
2
3
4
5
6
7
8
9
10
11
12private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = this.getServletContext();
if (webServer == null && servletContext == null) {
// 获取容器中的工厂类
ServletWebServerFactory factory = this.getWebServerFactory();
// 创建Web服务器实例
this.webServer = factory.getWebServer(this.getSelfInitializer());
}
// ...
}
这个过程中:
- Spring 容器从自身获取
ServletWebServerFactory
Bean(例如TomcatServletWebServerFactory
) - 调用工厂的
getWebServer()
方法创建实际的 Web 服务器 - 服务器启动并绑定到配置的端口(默认 8080)
其中的 refresh()
容器刷新十二大步如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh(); // 第10步:刷新子容器
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var10) {
BeansException ex = var10;
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + ex);
}
this.destroyBeans();
this.cancelRefresh(ex);
throw ex;
} finally {
this.resetCommonCaches();
contextRefresh.end();
}
}
}
总结出来就是一句话,Web 场景的 Spring 容器启动,在 onRefresh 的时候,会调用创建 Web 服务器的方法
而 Web 服务器的创建是通过
WebServerFactory
搞定的。容器中又会根据导了什么包条件注解,启动相关的服务器配置,默认EmbeddedTomcat
会给容器中放⼀个TomcatServletWebServerFactory
,导致项目启动,⾃动创建出Tomcat。
sequenceDiagram
participant App as 应用启动
participant AutoConfig as 自动配置
participant Container as Spring容器
participant Factory as 服务器工厂
participant Server as Web服务器
App->>AutoConfig: 加载ServletWebServerFactoryAutoConfiguration
AutoConfig->>AutoConfig: 检查条件注解
AutoConfig->>AutoConfig: 导入对应容器配置
AutoConfig->>Container: 注册ServletWebServerFactory
App->>Container: 调用refresh()
Container->>Container: 执行onRefresh()
Container->>Factory: 获取WebServerFactory
Factory->>Server: 创建WebServer实例
Server->>Server: 启动并监听端口
Server-->>Container: 返回WebServer
Container-->>App: 启动完成
自定义嵌入式 Servlet 容器
为什么 Tomcat 是默认的容器
这就涉及到 Spring Boot 的默认绑定机制
1 | <dependency> |
自动包含
spring-boot-starter-tomcat
传递依赖依赖关系可通过
mvn dependency:tree
查看:1
2[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.7.0
[INFO] | \- org.springframework.boot:spring-boot-starter-tomcat:jar:2.7.0
而Reactive Web 应用
1 | <dependency> |
- 其中自动包含
reactor-netty
核心依赖

1 | <!--引入springboot父依赖--> |
如何切换嵌入式 Servlet 容器
Spring Boot 支持四种嵌入式容器实现,分别对应不同的技术场景:
容器类型 | 技术类型 | 默认绑定启动器 | 特点 |
---|---|---|---|
Tomcat | Servlet Web | spring-boot-starter-web | 默认实现,稳定性高 |
Jetty | Servlet Web | spring-boot-starter-jetty | 高性能,适合长连接场景 |
Undertow | Servlet Web | spring-boot-starter-undertow | 低内存消耗,非阻塞IO模型 |
Netty | Reactive Web | spring-boot-starter-webflux | 异步非阻塞,高并发处理 |
以上 Web 容器均被 Spring Boot
嵌入至其中作为其核心特性,来简化
Spring Boot
应用启动流程。Spring Boot
通过
Maven
依赖来切换应用的嵌入式容器类型,其对应的 Maven jar
分别是:
1 | <!-- Tomcat --> |
前三者是 Servlet Web
实现,最后则是
Reactive Web
的实现。值得注意的是,当我们引用的是
Servlet Web
功能模块时,它会自动集成 Tomcat
,里面包含了 Tomcat
的 Maven
依赖包,也是印证了上面说的 Tomcat
是默认的
Servlet Web
容器。Servlet Web
模块的
Maven
依赖就是 web 启动场景:
1 | <dependency> |
而如果引用的是 Reactive Web
功能模块时,则会默认集成
netty Web Server
。Reactive Web
模块的依赖如下:
1 | <dependency> |
不过,上面的三种 Servlet Web
容器也能作为
Reactive Web
容器 ,并允许替换默认实现
Netty Web Server
,因为 Servlet
3.1+容器同样满足 Reactive
异步非阻塞特性。
我们需要切换不同的容器,就需要在启动器依赖里把 Tomcat 给排除,然后换成自己需要的容器类型
1 | <dependency> |
如果需要切换到 Netty 也是一样
因为web里引入的是tomcat容器,所以这里首先排除tomcat容器,然后引入Netty容器
1 | <!--引入springboot父依赖--> |
而其中装配什么就生效什么,也是依赖于上述的条件装配机制,每个容器配置类都有@ConditionalOnClass
注解,并且通过spring-autoconfigure-metadata.json
定义加载顺序
graph TD
A[启动应用] --> B[检测类路径]
B --> C{存在Tomcat类?}
C -->|是| D[加载Tomcat工厂]
C -->|否| E{存在Jetty类?}
E -->|是| F[加载Jetty工厂]
E -->|否| G[加载Undertow工厂]
我们可以通过使用如下代码确认当前容器
1 |
|
但是更常用的从启动日志分析就可以看出
1 | o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) |
关键日志标识:
- Tomcat:
o.s.b.w.embedded.tomcat
- Jetty:
o.s.b.w.embedded.jetty
- Undertow:
o.s.b.w.embedded.undertow
如果同时存在多个容器依赖
Spring Boot会按以下优先级选择:
- Tomcat
- Jetty
- Undertow
也可以通过
@Order
注解控制:1
2
public class MyCustomContainerAutoConfiguration {}
不同Spring Boot版本对容器的支持存在差异:
Spring Boot | Tomcat | Jetty | Undertow | Netty |
---|---|---|---|---|
2.7.x | 9.0 | 9.4 | 2.2 | 1.0 |
3.0.x | 10.0 | 11.0 | 2.3 | 1.1 |
建议通过spring-boot-dependencies
管理版本,避免冲突。
三种机制
Spring Boot 提供了灵活的机制来定制嵌入式 Tomcat 容器,开发者可通过配置文件、工厂类定制或完全自定义配置三种方式实现。
容器选择机制
Spring Boot 根据类路径中的依赖自动选择容器:
- 默认使用 Tomcat(
spring-boot-starter-web
包含 Tomcat 依赖) - 若排除 Tomcat 并添加 Jetty/Undertow 依赖,则自动切换
工厂类的作用:
当容器选择完成后,对应的工厂类会被注册到 Spring 容器中:
- Tomcat:
TomcatServletWebServerFactory
- Jetty:
JettyServletWebServerFactory
- Undertow:
UndertowServletWebServerFactory
这些工厂类实现了 ServletWebServerFactory
接口,负责创建和配置具体的 Web 服务器实例。
以Tomcat为例子,展示如何配置
通过配置文件定制 Tomcat 参数
在 application.properties
或
application.yml
中通过 server.tomcat
前缀配置
Tomcat 特性,以下是常用配置项:
1 | # 基础服务器配置 |
通过工厂类定制 Tomcat 组件
通过自定义 TomcatServletWebServerFactory
Bean
实现更深度的定制
1 | import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; |