






















基于Spring Boot的web应用中,在spring-boot包内包含了内置的 web server,具体包括 tomcat、jetty、undertow 和 netty。
本文旨在厘清spring boot中内置server的原理和使用。
首先我们跟踪一下 org.springframework.boot:spring-boot 包中 org.springframework.boot.web package下的代码,代码可以看 Github spring-boot
package下的目录结构如下:
spring-boot-starter-webflux包spring-boot-starter-web 包
Spring Framework 5.0 提供了两种web框架,分别是 servlet 和 reactive ,他们具体的不同如下
servlet 是Spring Web中引入,基于servlet API实现,即Spring MVC;
reactive 是通过Spring Webflux引入,实现了Reactive Streams 规范的响应式
servlet 实现的是阻塞IO (blocking I/O)
reactive 实现的是 Event-Loop,非阻塞IO(non-blocking I/O),即异步处理
针对servlet 框架,SpringBoot提供了三种内置Server,分别是 Jetty、Tomcat 和 Undertow
针对reactive 框架,SpringBoot提供了四种内置Server,分别是 Jetty、Tomcat、Undertow 和 Netty

这部分我们介绍一下 WebServer 接口与实现,WebServer提供的5个方法如下:
然后我们来看看 WebServer 的实现,实现主要是spring-boot中内置的几个Server,具体有:
org.eclipse.jettyio.projectreactor 和 io.nettyorg.apache.tomcatio.undertow目前我们知道了SpringBoot中内置的WebServer提供了这些实现,那么在服务启动时,默认使用的是哪个 Server 呢?
spring-boot-starter-web 中默认依赖了spring-boot-starter-tomcat。spring-boot-starter-webflux 中默认依赖了 spring-boot-starter-reactor-netty。
SpringBoot中提供了WebServerFactory的工厂接口类,用来封装WebServer的创建
WebServerFactory也分为了两种即 ServletWebServerFactory 和 ReactiveWebServerFactory,两者都提供了getWebServer 方法来创建WebServer,但具体有所不同
ServletWebServerFactory 提供的getWebServer 方法传入的参数是org.springframework.boot.web.servlet.ServletContextInitializer,用于配置Servlet 3.0+的接口。
ServletContextInitializer中提供了onStartup(ServletContext servletContext) 方法
其中jakarta.servlet.ServletContext用于连接对应的servlet容器
ReactiveWebServerFactory 提供的getWebServer 方法传入的参数是org.springframework.http.server.reactive.HttpHandler。
HttpHandler中提供了handle(ServerHttpRequest request, ServerHttpResponse response)方法
其中 org.springframework.http.server.reactive.ServerHttpRequest和org.springframework.http.server.reactive.ServerHttpResponse 对应的则是基于reactive server的 request 和 response
| Server | Servlet stack | Reactive stack |
|---|---|---|
| Tomcat | TomcatServletWebServerFactory | TomcatReactiveWebServerFactory |
| Jetty | JettyServletWebServerFactory | JettyReactiveWebServerFactory |
| Undertow | UndertowServletWebServerFactory | UndertowReactiveWebServerFactory |
| Reactor | N/A | NettyReactiveWebServerFactory |
WebServerFactory具体的接口和实现类如下图,这里不再做详细说明

上面我们梳理了 WebServer 和 用于管理的工厂类 WebServerFactory,下面我们来剖析SpringBoot中是如何通过Factory管理Server Bean的。
创建了对应的ServletWebServerApplicationContext和ReactiveWebServerApplicationContext ,并在这两个类实现了 onRefresh() 方法,此方法用于在特定context子类中初始化特殊的bean,这里所指的特定context子类包含ServletWebServerApplicationContext、ReactiveWebServerApplicationContext 和 StaticWebApplicationContext,具体如下:
ServletWebServerApplicationContext 中,onRefresh() 方法中获取 ServletWebServerFactory Bean 创建 WebServerReactiveWebServerApplicationContext 中,onRefresh() 方法中获取ReactiveWebServerFactory Bean,并创建WebServerManager,在 WebServerManager 的构造方法中创建了 WebServerStaticWebApplicationContext中,onRefresh() 方法用于创建 ThemeSource 的静态主题
这里不会展开介绍这4种Server的实现和区别,只是稍微简述一下实现和不同点。
Tomcat目前收录与 Apache 项目中,官方链接是https://tomcat.apache.org/
Tomcat是主流的Java Web Server,所以是十分稳定和成熟的,同时社区活跃文档和资源丰富。
Tomcat可以支持Http, Http/2 , AJP, WebSocket 协议,支持Servlet 6.0
Jetty是 Eclipse 提供的一款Server,官方链接是https://eclipse.dev/jetty/documentation.php
相比Tomcat它更加轻量级,有自己的异步支持。
Jetty可以支持Http, Http/2 ,Http/3, AJP, WebSocket 协议,支持Servlet 6.0
Netty是一个基于时间驱动的异步网络框架,被广泛应用于高性能的网络应用程序,尤其是处理大量并发连接的服务端应用,官方链接是https://netty.io/index.html。
Netty几乎支持了大部分的协议,有**SSL/TLS, ** HTTP, ** HTTP/2**, HTTP/3, WebSockets, DNS, ** SPDY **, SMTP 等
Undertow是 JBoos 提供的一款Server,官方地址是https://undertow.io/
Undertow的特点在于轻量级、高性能和地资源消耗,同时支持嵌入式应用程序和微服务。
Undertow可以支持Http, Http/2 , WebSocket 协议,支持Servlet 4.0
这里贴一下基于Tomcat/Jetty/Undertow的Server运行情况,主要监控了 内存使用、类加载、线程数、每秒请求书 和 每个请求的平均处理时长。
我们可以得知,内存占用和类加载方面,Jetty更加轻量;处理请求数和响应时间方面,Undertow速度更快。
| Metric | Tomcat | Jetty | Undertow |
|---|---|---|---|
| jvm.memory.used (MB) | 168 | 155 | 164 |
| jvm.classes.loaded | 9869 | 9784 | 9787 |
| jvm.threads.live | 25 | 17 | 19 |
| Requests per second | 1542 | 1627 | 1650 |
| Average time per request (ms) | 6.483 | 6.148 | 6.059 |
最后一部分我们介绍一下如何在 SpringBoot 中使用非默认的 Server
在 Servlet 框架下使用 Jetty:
<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>
在 Reactive 框架下使用 Jetty:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-reactor-netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
在 Servlet 框架下使用 Undertow:
<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-undertow</artifactId>
</dependency>
在 Reactive 框架下使用 Undertow:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-reactor-netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-reactor-netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
如果原有是基于SpringMVC的项目,想使用Netty Server,需要依赖SpringWebflux
值得注意的是 SpringWebflux 也是支持@Controller、@RestController 等传统SpringMVC注解的,具体实现的类是AnnotationConfigReactiveWebServerApplicationContext ,它是ReactiveWebServerApplicationContext 的子类。
<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-webflux</artifactId>
</dependency>
Spring 5的Servlet和反应式技术栈解析_Java_Rossen Stoyanchev_InfoQ精选文章
Comparing Embedded Servlet Containers in Spring Boot | Baeldung
SpringBoot 2 performance — servlet stack vs WebFlux reactive stack
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。