javascript
SpringBoot 嵌入式Servlet容器
一、嵌入式Servlet容器
- 默認支持的webServer :Tomcat, Jetty, or Undertow
- ServletWebServerApplicationContext 容器啟動尋找ServletWebServerFactory并引導創建服務器
切換服務器
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!--排除默認導入的tomcat--><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions> </dependency>我們知道Springboot的自動配置都是通過一些AutoConfiguration類進行自動配置的,所以同理本博客也找一些對應的類,ServletWebServerFactoryAutoConfiguration 就是嵌入式servlet容器的自動配置類,簡單跟一下其源碼:
從自動配置類里,我們并不能很明確地理解自動配置是怎么運行的,只看重關鍵的一些信息點,比如注冊了Tomcat的ServletWebServer工廠的定制器類,方法是tomcatServletWebServerFactoryCustomizer,還有一個后置處理類BeanPostProcessorsRegistrar,后置處理是Spring源碼里是很關鍵的,所以這里可以繼續點一下TomcatServletWebServerFactoryCustomizer,Tomcat的webServer工廠定制器類
也是一個WebServerFactoryCustomizer類型的類,這個類是進行servlet容器的一些定制
這個是關鍵的方法,主要是拿ServerProperties配置類里的信息進行特定屬性定制
所以,這里就可以知道Tomcat的配置是通過定制器類TomcatServletWebServerFactoryCustomizer進行定制的,其工廠類是TomcatServletWebServerFactory
TomcatServletWebServerFactory工廠類進行Tomcat對象的創建,必要參數的自動配置
ok,簡單跟了一下源碼之后,我們知道了TomcatServletWebServerFactoryCustomizer是Tomcat的定制器類,Tomcat對象的創建是通過TomcatServletWebServerFactory類的,然后,有個疑問,這個定制器類是什么時候創建的?為什么一啟動Application類,嵌入式的Tomcat也啟動了?打成jar格式的Springboot項目,只要運行jar命令,不需要啟動任何servlet容器,項目也是正常運行的?然后這個BeanPostProcessorsRegistrar后置處理類有什么作用?ok,帶著這些疑問,我們還是用調試一下源碼
如圖,打斷點調試,看看Tomcat定制器是怎么創建的?
定制器類被調用了,其對應的工廠類也會起作用,打個斷點,看看工廠類是怎么調用的?
ok,啟動Application類,在idea里調試,如圖,可以跟著調用順序,一點點跟源碼,如圖所示,調用了Springboot的run方法
run方法里的刷新上下文方法,refreshContext其實也就是創建ioc容器,初始化ioc容器,并創建容器的每一個組件
這里注意到了,調用到了ServletWebServerApplicationContext類的refresh方法,ServletWebServerApplicationContext類前面也介紹到了,這個類是一種特殊的ApplicationContext類,也就是一些ioc的上下文類,作用于WebServer類型的類
創建webServer類,先創建ioc容器,調用基類的onRefresh方法,然后再調用createWebServer方法
ioc的servletContext組件沒被創建的情況,調用ServletWebServerFactory類獲取WebServer類,有servletContext的情況,直接從ioc容器獲取
掃描ioc容器里是否有對應的ServletWebServerFactory類,TomcatServletWebServerFactory是其中一種,通過調試,是有掃描到的,所以從ioc容器里將這個bean對應的信息封裝到ServletWebServerFactory對象
接著是ioc容器創建bean的過程,這個一個比較復雜的過程,因為是單例的,所以是調用singleObjects進行存儲
bean被創建之后,調用了后置處理器,這個其實就是Spring的源碼里的bean的創建過程,后置處理器是很關鍵的,在bean被創建,還沒進行屬性賦值時候,就調用了后置處理器
關鍵點,這里是檢測是否有WebServerFactory工廠類,前面的調試發現已經有Tomcat的WebServer工廠類,所以是會調用后置處理器的
調用了WebServerFactoryCustomizerBeanPostProcessor這個后置處理類,然后拿到一個WebServerFactoryCustomizer定制器類,也就是TomcatWebServerFactoryCustomizer,通過后置處理器調用定制方法customize
然后WebServerFactoryCustomizerBeanPostProcessor這個后置處理器是什么注冊的?往前翻Springboot的自動配置類,在這里找到了WebServerFactoryCustomizerBeanPostProcessor的注冊
ok,繼續調試源碼,BeanWrapperImpl創建bean實例
ok,Tomcat定制器類被調用了,是通過后置處理器調用的
然后就是之前跟過的定制方法customize執行:
Tomcat的WebServer工廠類創建Tomcat對象實例,進行屬性配置,引擎設置等等
端口有設置就創建TomcatwebServer對象
TomcatWebServer啟動Tomcat,如圖代碼所示:
ok,跟了源碼,您是否有一個疑問?Tomcat的工廠類TomcatServletWebServerFactory是什么時候創建的?好的,返回前面配置類看看,如圖,這里用import引入了EmbeddedTomcat類
ok,EmbeddedTomcat是一個內部的配置類,條件是有引入Tomcat對應的jar,就會自動創建工廠類,很顯然,Springboot默認是有引入的
ok,經過源碼比較簡單的學習,思路就很清晰了,Springboot的ServletWebServerFactoryAutoConfiguration是嵌入式Servlet容器的自動配置類,這個類的主要作用是創建TomcatServletWebServerFactory工廠類,創建定制器類TomcatServletWebServerFactoryCustomizer,創建FilterRegistrationBean類,同時很關鍵的一步是注冊后置處理器webServerFactoryCustomizerBeanPostProcessor,然后Springboot的Application類一啟動,就會執行run方法,run經過一系列調用會通過ServletWebServerApplicationContext的onRefresh方法創建ioc容器,然后通過createWebServer方法,createWebServer方法會去ioc容器里掃描是否有對應的ServletWebServerFactory工廠類(TomcatServletWebServerFactory是其中一種),掃描得到,就會觸發webServerFactoryCustomizerBeanPostProcessor后置處理器類,這個處理器類會獲取TomcatServletWebServerFactoryCustomizer定制器,并調用customize方法進行定制,這時候工廠類起作用,調用getWebServer方法進行Tomcat屬性配置和引擎設置等等,再創建TomcatWebServer啟動Tomcat容器,ok,本博客只是簡單跟一下嵌入式Tomcat容器的啟動過程,可以看出Springboot的強大,還是基于Spring框架的,比如本文提到的后置處理器,以及bean工程創建bean實例的過程,都是通過Spring框架實現的。
二、總結
三、定制Servlet容器
- 把配置文件的值和ServletWebServerFactory 進行綁定
修改配置文件 server.xxx
直接自定義 ConfigurableServletWebServerFactory
xxxxxCustomizer:定制化器,可以改變xxxx的默認規則
import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; import org.springframework.stereotype.Component; @Component public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {@Overridepublic void customize(ConfigurableServletWebServerFactory server) {server.setPort(9000);} }部分轉自
總結
以上是生活随笔為你收集整理的SpringBoot 嵌入式Servlet容器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot Web原生组件注入
- 下一篇: 未来的语音世界——中国智能语音市场分析