深度解析SpringBoot內嵌Web容器
SpringBoot提供的內嵌容器
SpringBoot提供了四種Web容器,分別為Tomcat,Jetty,Undertow,Netty。
Tomcat
Spring Boot 默認使用 Tomcat 作為嵌入式 Web 容器。Tomcat 作為一個流行的 Web 容器,容易能夠理解、配置和管理??梢酝ㄟ^使用spring-boot-starter-web來啟用 Tomcat 容器。
Jetty
Jetty 同樣是一個流行的嵌入式 Web 容器,它的缺省配置相對精簡,從而有利快速啟動。可以通過使用spring-boot-starter-jetty來啟用 Jetty 容器。
Undertow
Undertow 是一個由 JBoss 開發(fā)的輕量級的嵌入式 Web 服務器。它具有出色的性能和低資源占用率,是一個適合微服務實現(xiàn)的 Web 服務器??梢允褂胹pring-boot-starter-undertow來啟用 Undertow 容器。
Netty
Netty是一個高性能的網絡框架,需要引入spring-boot-starter-webflux和spring-boot-starter-reactor-netty來開啟Netty作為Web容器。
使用
因為SpringBoot默認的是Tomcat作為Web容器,如果我們需要使用使用其他Web容器,那么需要排除Tomcat容器,再引入其他容器,Tomcat容器位于spring-boot-starter-web模塊下,所以我們需要在maven的pom.xml中移除Tomcat,如下。
<dependency> ??????<groupId>org.springframework.boot</groupId> ??????<artifactId>spring-boot-starter-web</artifactId> ??????<version>3.0.2</version> ??????<exclusions> ??????????<exclusion> ??????????????<groupId>org.springframework.boot</groupId> ??????????????<artifactId>spring-boot-starter-tomcat</artifactId> ??????????</exclusion> ??????</exclusions> </dependency>
然后引入對應的Web容器,比如引入Undertow
<dependency> ??????<groupId>org.springframework.boot</groupId> ??????<artifactId>spring-boot-starter-undertow</artifactId> </dependency>
然后可以在yml文件中配置相應容器的參數(shù),如下配置undertow.
server: ??port:?8080 ??undertow: ????threads: ??????worker:?10 ??????io:?10 ????direct-buffers:?true
其他web容器可以根據實際情況配置,從ServerProperties配置文件中可以查看對應的Web容器的相關配置。

源碼解析
下面從源碼進行分析,我們先使用SpringBoot的默認Web容器Tomcat進行分析。
那么源碼應該從哪里看起呢,對于SpringBoot這么龐大復雜的項目,首先,我們在使用SpringBoot的時候,需要在application.yml文件中配置相關信息,比如端口,如果不配置端口,默認是8080,那么這個端口肯定是web容器的端口,如果是Tomcat,那么Tomcat就設置為這個端口,Undertow也是,依此類推。
那么這里就是一個入口,在SpringBoot中,我們要獲取yml文件中的配置信息,一般是通過@ConfigurationProperties注解,我們可以按住ctrl,然后鼠標點擊這個port,就能跳到對應的屬性類里面。

屬性類ServerProperties就是專門獲取yml文件中的配置,然后以供使用。

到了屬性類里面后,我們繼續(xù)ctrl,然后會彈出很多類,如下所示。

因為我們使用的是Tomcat,那么就選擇一個Tomcat相關的類,我們選擇TomcatWebServerFactoryCustomizer,這個類實現(xiàn)了接口WebServerFactoryCustomizer,并實現(xiàn)了方法customize。

customize的參數(shù)是ConfigurableTomcatWebServerFactory,它是一個接口,它還繼承了接口ConfigurableWebServerFactory,我們從ConfigurableWebServerFactory中看出里面有設置端口,地址等方法。

我們再回頭看ConfigurableTomcatWebServerFactory,可以看出里面是一些Tomcat相關的方法。

然后繼續(xù)看ConfigurableUndertowWebServerFactory,可以看出里面是對Undertow的一些屬性設置的方法。

我們回到TomcatWebServerFactoryCustomizer類中,SpringBoot使用了它的PropertyMapper類對屬性進行設置,我們可以看出它使用propertyMapper.from().to()語法,其實就是將ServerProperties中的屬性設置到ConfigurableTomcatWebServerFactory中,這個屬性設置是在Spring對Bean進行初始化時候設置的,使用的是Spring的后置處理器來實現(xiàn)的,后面我們繼續(xù)說。

然后我們繼續(xù)看一下TomcatWebServerFactoryCustomizer,他有一個構造函數(shù),參數(shù)是Environment和ServerProperties,那么就證明其他地方對其進行了new操作。

我們也是用ctrl套路,點擊構造函數(shù)后跳到了EmbeddedWebServerFactoryCustomizerAutoConfiguration自動裝配類中,這個類中有四個靜態(tài)類,我們可以看出,他們的作用都是創(chuàng)建對應的定制器Bean,其實就是將yml文件中的Web容器配置進行裝配,以供后面使用。

上面說的這一堆其實就是SpringBoot的自動裝配,其目的就是創(chuàng)建對應的Customizer,因為每個Web容器的配置項不一樣,所以就需要不同的Customizer和Factory。
上面說了這么多,怎么感覺和源碼沒關系呢,沒錯,其實上面說的并不是核心源碼,那么怎么找到核心源碼呢?我們思考一下,既然上面是部分源碼,那么源碼肯定會執(zhí)行到這里。
查看調用鏈
我們在上面的TomcatWebServerFactoryCustomizer類中的customize方法中打一個斷點,然后debug,于是得到調用鏈如下。

我們可以看出會調用onRefresh()方法,因為AbstractApplicationContext使用的是模板方法模式,具體的實現(xiàn)交給子類實現(xiàn),因為使用的是Tomcat,所以交給了ServletWebServerApplicationContext類來實現(xiàn),具體的子類里面有一個createWebServer()方法,它就是創(chuàng)建Web容器。

具體實現(xiàn)如下,如下是Tomcat的實現(xiàn),里面會涉及到兩個重要的接口WebServer和WebServerFactory。

WebServer
WebServer是容器的頂層接口,具體實現(xiàn)交給具體的容器實現(xiàn)類,如Tomcat則使用TomcatWebServer,Undertow則使用UndertowWebServer,Jetty,Netty也是如此。
此接口提供了一些方法,start()啟動Web服務器,stop()停止Web服務器,getPort()獲取服務器端口。

不過對于start()和stop(),它們只是接口抽象的規(guī)范,在具體的實現(xiàn)中,也并不是全部都按照這個標準,start()方法上有備注Starts the web server. Calling this method on an already started server has no effect.,翻譯為:啟動web服務器。在已啟動的服務器上調用此方法無效。,比如Tomcat的就沒有在start()方法中啟動服務器,具體我們等會會看。
WebServerFactory
WebServerFactory是一個接口,沒有定義任何方法,它就創(chuàng)建Web服務器的工廠的標記接口,Spring中很多地方也是這樣的風格。

這個接口重要的兩個子接口,也是我們需要關注的兩個子接口分別是ServletWebServerFactory和ReactiveWebServerFactory,它們兩個都定義了一個方法getWebServer。
Jetty,Undertow,Tomcat三個都屬于Servlet容器,所以使用的是ServletWebServerFactory來創(chuàng)建Web容器。

而Netty不是Servlet容器,所以使用的是ReactiveWebServerFactory來創(chuàng)建Web容器。

上面對這兩個接口進行了介紹,基本上整個Web容器都是圍繞這兩個接口來,我們下面繼續(xù)分析。
獲取WebServerFactory
首先我們要先獲取web服務的工廠類的Bean,才能創(chuàng)建Web容器,因為我們使用的是Tomcat,所以獲取到的工廠類是TomcatServletWebServerFactory,具體的獲取Bean的過程我們就沒有必要去一一說明,只要對Spring IOC稍微熟悉一點就能理解,我們主要說一下在后置處理器。
上面我們介紹了Tomcat容器的定制器Customizer,里面對Web容器的配置屬性進行組裝,它就是發(fā)生在Bean的初始化前,用到的Bean后置處理器是WebServerFactoryCustomizerBeanPostProcessor。

Bean的后置處理器中,會調用對應的定制器,Tomcat調用的就是TomcatWebServerFactoryCustomizer,其他的也一樣,其目的都是定制WebServerFactory。
經過一系列處理后,就從IOC容器中獲取到了WebServerFactoryBean,然后再使用這個工廠去創(chuàng)建Web服務。
創(chuàng)建Web服務
獲取到WebServerFactory后,就可以創(chuàng)建Web容器,因為使用的是Tomcat,所以使用的是TomcatServletWebServerFactory,如下,我們就看到了Tomcat的身影。

最后啟動Tomcat容器是在TomcatWebServer中,在TomcatWebServer的構造函數(shù)中調用initialize(),在initialize()中我們看是this.tomcat.start(),Tomcat被啟動了。

上面我們在說WebServer接口的時候,說了啟動start()方法,在Tomcat的實現(xiàn)中就沒有使用start()來啟動容器,但是在Undertow中,就使用了start()方法來啟動容器。
Undertow容器啟動
上面我們介紹了Tomcat容器的創(chuàng)建,Undertow的流程和Tomcat基本上是一樣的,但是在啟動的時候,Undertow是在start()方法中啟動,而start()方法需要在 finishRefresh()這一步中執(zhí)行。

在finishRefresh()中,會調用生命周期處理器

最終會走到WebServerStartStopLifecycle這個生命周期,這里就會調用WebServer中的start()方法。

最終在UndertowWebServer中啟動Undertow容器

具體執(zhí)行順序如下。
finishRefresh() -> getLifecycleProcessor().onRefresh() -> startBeans(true) -> start() -> doStart(this.lifecycleBeans, member.name, this.autoStartupOnly) -> bean.start() -> this.webServer.start()
上面我們分析了Tomcat和Undertow的創(chuàng)建流程,Jetty和Netty也是大同小異,因為Spring使用了模板方法模式,具體的實現(xiàn)交給具體的Web容器,所以在整體結構上是差不多的,只是實現(xiàn)方式不同。
總結
關于SpringBoot的內嵌Web容器,就說得差不多了,我們從各種Web容器進行介紹,包括他們的有點,怎么在SpringBoot中使用,并對源碼進行解析,在源碼解析這里,我們并沒有進行芝麻細節(jié)式解析,而是從大體上進行解析,只有對大致結構了解,才能更好地進行深度學習。
SpringBoot內嵌容器涉及的知識點還是比較多,需要對Spring和SpringBoot有一定的了解才能更好地學習它,本文基于SpringBoot3.0進行解析, SpringBoot3.0中,Servlet也是遵循Jakata EE規(guī)范。
以上就是深度解析SpringBoot內嵌Web容器的詳細內容,更多關于SpringBoot Web容器的資料請關注腳本之家其它相關文章!
相關文章
springboot連接mongo性能優(yōu)化參數(shù)配置方式
這篇文章主要介紹了springboot連接mongo性能優(yōu)化參數(shù)配置方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-06-06
Spring?Cloud?Sleuth?和?Zipkin?進行分布式跟蹤使用小結
分布式跟蹤是一種機制,我們可以使用它跟蹤整個分布式系統(tǒng)中的特定請求,分布式跟蹤允許您跟蹤分布式系統(tǒng)中的請求,本文給大家介紹Spring?Cloud?Sleuth?和?Zipkin?進行分布式跟蹤使用小結,感興趣的朋友一起看看吧2022-03-03
SpringBoot基于線程池的訂單創(chuàng)建并行化實踐過程
文章介紹了電商系統(tǒng)訂單創(chuàng)建接口的并行處理方案,通過分析業(yè)務流程、選擇合適的線程池和技術,解決了高并發(fā)場景下的性能問題2025-12-12
RocketMQ?broker?消息投遞流程處理PULL_MESSAGE請求解析
這篇文章主要為大家介紹了RocketMQ?broker?消息投遞流程處理PULL_MESSAGE請求源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04

