Spring Boot 支持的 Web 容器,需要根据你使用的是传统的 Servlet 技术栈还是响应式技术栈来区分。
Servlet 技术栈(对应 spring-boot-starter-web)
根据 Spring Boot 官方文档,主要支持以下三种嵌入式容器:
Tomcat :这是 Spring Boot 的默认容器,引入 spring-boot-starter-web 时自动包含。
Jetty :轻量级容器,常用于需要快速启动或长连接(如 WebSocket)的场景。
Undertow :由 JBoss 开发,以低内存占用和高吞吐量见长。
如果你确实想用 Jetty 或 Undertow,需要手动修改依赖配置:
排除 Tomcat:从 spring-boot-starter-web 中排除 spring-boot-starter-tomcat。
引入新容器:添加 spring-boot-starter-jetty 或 spring-boot-starter-undertow 依赖。
响应式技术栈(对应 spring-boot-starter-webflux)
如果你使用的是 WebFlux,容器选择有所不同:
Reactor Netty :这是 WebFlux 的默认容器。
Jetty 与 Undertow :同样提供对响应式栈的支持。
Tomcat:在响应式栈中通常不作为首选推荐,官方文档在列举响应式服务器工厂时也常将其排除在外
如何区分是传统的技术栈还是响应式技术栈?
方法一:看依赖(最准确)
打开你的 pom.xml(Maven)或 build.gradle(Gradle),搜索 spring-boot-starter 相关的依赖:
Servlet 技术栈:如果包含 spring-boot-starter-web,那就是 Servlet 栈,默认使用 Tomcat。
Reactive 技术栈:如果包含 spring-boot-starter-webflux,那就是响应式栈,默认使用 Reactor Netty。
需要注意,如果两者同时存在,Spring Boot 通常会优先选择 Servlet 栈(Spring MVC)。
方法二:看启动日志(最直观)
启动项目,观察控制台最后几行输出的服务器信息:
看到 Tomcat started on port(s): 8080,说明是 Servlet 栈 + Tomcat。
看到 Netty started on port(s): 8080,说明是 Reactive 栈 + Netty。
方法三:看代码里的注入类型(辅助判断)
如果你能接触到 Controller 代码,可以看方法参数或注入的类:
使用了 HttpServletRequest / HttpServletResponse,那是 Servlet 栈。
使用了 ServerHttpRequest / ServerHttpResponse,或者返回类型是 Mono、Flux,那是 Reactive 栈。
传统栈和响应式栈区别?
编程模型
-
传统栈(Spring MVC):命令式、同步。代码按顺序一行行执行,逻辑直观。
-
响应式栈(WebFlux) :响应式、异步非阻塞。基于 Reactor 的
Mono/Flux处理数据流。
线程模型(关键差异)
-
传统栈 :Thread-per-Request。每个请求分配一个线程,如果遇到数据库查询等 I/O 操作,该线程会被阻塞等待,直到操作完成。
-
响应式栈 :Event Loop。使用少量固定线程(事件循环线程)。当请求需要等待 I/O 时,线程不会阻塞,而是去处理其他请求,等数据就绪后再回来继续。
底层容器
-
传统栈 :基于 Servlet API,运行在 Tomcat、Jetty 等 Servlet 容器上。
-
响应式栈 :不依赖 Servlet API,默认运行在 Netty 等非阻塞服务器上。
背压(Backpressure)
-
传统栈 :不支持。如果上游数据产生速度远超下游处理速度,容易导致积压或资源耗尽。
-
响应式栈 :原生支持。下游可以告诉上游自己需要多少数据,实现流量控制。
适用场景
-
传统栈:绝大多数传统 Web 应用、管理后台、表单提交。生态极其成熟,调试简单,学习曲线平缓。
-
响应式栈:高并发、I/O 密集型场景(如微服务网关、实时聊天、流式推送)。能用少量资源支撑大量并发连接。
响应式栈并非在所有情况下都更快。性能表现取决于场景:
-
在网络 I/O 密集(如频繁调用外部 API、数据库)的场景下,WebFlux 的吞吐量优势明显。
-
在计算密集或逻辑简单的场景下,传统 MVC 配合调优的线程池,性能甚至可能更好,且代码更易于维护。