但是undetow依賴項的添加範圍沒有設置為provided,導致只要添加了這個依賴項,就會添加Undertow依賴項。恰好網關也使用了這種依賴,我們的網關使用的是Spring-Cloud-Gateway。這就導致了Spring-Cloud-Gateway的Netty的Reactive web容器被Undertow的Reactive web容器所替代,從而導致了Spring-Cloud-Gateway的壹系列不兼容問題。
我們知道Spring-Cloud-Gateway的底層實際上是基於Spring Boot的。首先,我們來看壹下Spring Boot初始化哪個web容器的選擇原則:首先,第壹步是根據類是否存在來確定是哪個WebApplicationType:
web應用程序類型
從源代碼可以看出,當有WEBFLUX_INDICATOR_CLASS而沒有WEBMVC_INDICATOR_CLASS和JERSEY_INDICATOR_CLASS時,判斷為反應式環境。如果所有的SERVLETs _ indicators _ classes都被認為是servlet環境。其實也可以看出,如果引入spring-web和spring-webflux,其實就是壹個SERVLET環境。如果以上都不是,那麽就是壹個沒有web容器的環境。在Spring-Cloud-Gateway中,它是壹個反應式的環境。
如果是反應式環境,將使用org的實現Bean創建壹個web容器。spring framework . boot . web . reactive . server . reactivewebserverfactory .那麽是哪個實現呢?目前有四種實現(Spring-boot 2.7.x):
哪個將實際用於查看哪個Bean將在ApplicationContext中註冊:
反應式web服務器工廠配置
從原代碼可以看出,每個配置都有@ ConditionalonMissingBean(ReactiveWebServiceFactory。class)以及判斷是否存在對應容器的類的條件,比如@ ConditionalonClass ({Undertow。類})。@ configuration(proxybean methods = false)是關閉這個配置中Bean之間的代理,以加快加載速度。
因為每個配置都有@ ConditionalonMissingBean(ReactiveWebServerFactory。Class),實際上可以保證即使滿足多個配置的條件,最後也只有壹個ReactiveWebServerFactory。那麽在滿足多個條件的情況下,先加載哪壹個呢?這取決於這裏的源代碼:
reactiveweb server factory auto configuration
由此可以看出,它是按照EmbeddedTomcat、EmbeddedJetty、EmbeddedUndertow和Embedded Dnetty的順序導入的,也就是說,只要妳的依賴項中添加了任何壹個web容器(比如Undertow),最終都會創建基於那個Web容器的異步容器,而不是基於netty。
首先,春雲網關的官方文件上寫著:
就是Spring雲網關只能在Netty的環境下運行。這是為什麽呢?在設計時,假定容器只能是網狀的。在開發Spring Cloud Gateway的各種內置過濾器和過濾器插件時,目前有很多代碼都是假設它是Netty的,比如用來緩存主體過濾器的工具類ServerWebExchangeUtils:
ServerWebExchangeUtils
從源代碼中可以看到,代碼直接認為響應中的BufferFactory是NettyDataBufferFactory,而在其他Web容器的情況下,目前應該是DefaultDataBufferFactory,所以會有例外。不過在v3.0.5之後的版本中,這個強開關已經被修復。參考:/Spring-Cloud/Spring-Cloud-Gateway/Commit/68dc 355119e 057 af 1e4f 664 c 814c 5。
這實際上是為兼容所有Web容器鋪平了道路。那麽,有沒有兼容所有Web容器的計劃呢?已經計劃好了,現在還在做。已經做了快四年了,應該快了,也就是說所有的單元測試都需要重新運行,甚至重新設計。妳可以通過這個問題:支持運行網關與其他反應容器基礎netty # 145。
查看兼容性的進度。