概述
Spring Cloud Gateway的路由裏包含了API的轉發邏輯、處理切面,是Spring Cloud Gateway最最關鍵的組件。在Spring Cloud Gateway裏有兩種添加路由的方式:一種是properties配置方式,一種是Java代碼配置方式。
一起看下,Spring Cloud Gateway路由配置信息轉化成路由對象,並且和RoutePredicateHandlerMapping建立關聯關係的過程。
路由初始化
Spring Cloud Gateway的路由延續了Spring一貫的做法,由RouteDefinition和Route兩個基礎類組成,RouteDefinition對應到properties文件中的路由描述,Route對應爲路由的內存數據結構。
RouteDefinitionLocator實現RouteDefinition的查找、解析,當前Spring Cloud Gateway支持3種形式的路由描述存儲方式,也就是上圖綠色的1,2,3:PropertiesRouteDefinitionLocator(properties文件)、DiscoveryClientRouteDefinitionLocator(服務發現)、InMemoryRouteDefinitionRepository(內存存儲,用於動態路由)。
CompositeRouteDefinitionLocator是一個合成器,集合裏上述3個路由,並且被註解爲了@Primary,所以路由定義解析的時候都會從CompositeRouteDefinitionLocator裏獲取路由描述,也就是能同時取出PropertiesRouteDefinitionLocator、DiscoveryClientRouteDefinitionLocator、InMemoryRouteDefinitionRepository
3種形式存儲的路由描述。
builder.routes().build()返回的是一個RouteLocator類型的實例,和CompositeRouteDefinitionLocator一樣,都會注入到CompositeRouteLocator裏,再封裝成CachingRouteLocator。
RoutePredicationHandlerMapping在處理webflux請求的時候,逐個調用RouteLocator中所有Route實例的Predicte.apply方法確定此次請求由哪個Route處理。
RouteDefinitionRouteLocator
RouteDefinitionRouteLocator用來把RouteDefinition轉換成Route,轉換過程在convertToRoute方法完成。
private Route convertToRoute(RouteDefinition routeDefinition) {
//1.解析predicate
AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);
//2.解析filters
List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);
//3.構建Route對象實例
return Route.async(routeDefinition).asyncPredicate(predicate)
.replaceFilters(gatewayFilters).build();
}
Predicate和GatewayFilter的解析邏輯類似,都是通過Definition.name()找到對應的解析Factory,然後完成Definition到對象實例的解析過程。
以下是PredicteFactory的內置實現:
以下是GatewayFilter的內置實現:
builder.routes().route(fn).build()
buidler是一個RouteLocatorBuilder類型的實例,在GatewayAutoConfiguration裏創建。
builder.route()創建一個內部類的實例,也就是RouteLocatorBuilder.Builder的實例,用來構建Route對象。
.route(fn)用來創建routeBuilder,並且添加到RouteLocatorBuilder.Builder的routes列表裏。
fn是一個FunctionalInterface接口,入參是PredicateSpec,返回值是Route.AsyncBuilder。
public Builder route(Function<PredicateSpec, Route.AsyncBuilder> fn) {
//fn的入參是一個RouteSpec對象
Route.AsyncBuilder routeBuilder = fn.apply(new RouteSpec(this).randomId());
//添加到routes列表
add(routeBuilder);
return this;
}
.build()返回一個RouteLocator,內部邏輯是逐個創建Route對象。
public RouteLocator build() {
return () -> Flux.fromIterable(this.routes)
.map(routeBuilder -> routeBuilder.build());
}