引言
上篇
實現Spring Cloud Gateway 動態路由和內建過濾器[1]
介紹了基於Spring Cloud Gateway實現動態路由和內建的過濾器。本著刨根問底的精神,我不禁想到Spring Cloud Gateway的過濾器是如何載入的? 我們都知道在Spring 5。X版本中出現了WebFlux,它是Spring 5。x框架的一部分,為Web應用提供了響應式程式設計的支援;而Spring Cloud Gateway 又是基於WebFlux實現的。
所以,今天我們來看看Spring Cloud Gateway是如何與Web Flxu進行契合的。
Gateway 切入點
我們知道在SpringMVC當中是透過
DispatcherServlet
進行請求的處理和轉發的,而在Spring WebFlux當中也有類似的類:
DispatcherHandler
在
DispatcherHandler
類中,我們可以在
handle
方法當中看到根據當前的請求資訊
ServerWebExchange
從
handlerMappings
屬性中獲取對應的Handler例項,然後進行呼叫。
@Overridepublic Mono
我們再看看
handlerMappings
屬性,它是一個
List
列表,該屬性的值是透過initStrategies方法從Spring容器當中獲取的。
protected void initStrategies(ApplicationContext context) { Map
而在眾多的
HandlerMapping
例項當中,我們可以找到其中一個Spring Cloud Gateway的實現類:
RoutePredicateHandlerMapping
, 這個類是在
GatewayAutoConfiguration
類中透過@Bean註解進行例項化的,其中還透過構造器注入了一個很重要的例項:
RouteLocator
。
到這裡,我們回頭看下在
DispatcherHandler
類的
handle
方法中,是透過呼叫
HandlerMapping#getHandler
方法返回某個handler物件,然後在進行呼叫。
所以,在
RoutePredicateHandlerMapping
例項當中,其實就是呼叫了父類的
getHandler
方法,繼而呼叫了
RoutePredicateHandlerMapping#getHandlerInternal
方法。
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) { if (this。managementPortType == DIFFERENT && this。managementPort != null && exchange。getRequest()。getURI()。getPort() == this。managementPort) { return Mono。empty(); } exchange。getAttributes()。put(GATEWAY_HANDLER_MAPPER_ATTR, getSimpleName()); return lookupRoute(exchange) 。flatMap((Function
最後會走到
RoutePredicateHandlerMapping#lookupRoute
方法。
protected Mono
看到這裡,想必你已經明白了,最後是根據當前請求對路由進行匹配,如果匹配則快取到當前請求資訊上下文中,然後返回對應的
FilteringWebHandler
例項。
最後,放一張
RoutePredicateHandlerMapping
的類圖
Gateway Filter 處理流程
透過上一節,我們已經明白了Gateway是如何切入WebFlux的處理流程的。現在我們再看看對於Spring Cloud Gateway 過濾器框架是如何處理的。
在說Spring Cloud Gateway的過濾器處理流程之前,我們需要先知道在Gateway有2種類型的過濾器:
•
GlobalFilter
公共型別的過濾器,所有的路由都會載入這種型別的過濾器
•
GatewayFilter
特殊型別的過濾器,只有顯示掛載到某個過濾器,才會進行對應的邏輯處理
在上一節,我們知道
DispatcherHandler#handle
方法最後是做了2個事情:
1。根據請求資訊匹配到對應的路由物件,並且放到當前請求的上下文中2。返回
FilteringWebHandler
例項
我們接著往下走,在
DispatcherHandler#invokeHandler
方法進行方法呼叫,會走到
FilteringWebHandler#handle
。
public Mono
在該方法內,從當前請求的上下文取回Route物件,然後組裝過濾器,
GlobalFilter
和
GatewayFilter
合併成一個列表,最後放到過濾鏈中進行邏輯處理。
總結
透過以上一步一步的梳理,終於搞明白了Spring Cloud Gateway 是如何和WebFlux進行結合的,並且其中最重要的Filter是如何工作的。
以上,如果有哪裡不對,歡迎討論。
References
[1] 實現Spring Cloud Gateway 動態路由和內建過濾器:
https://juejin。cn/post/7038231474465669157