spring cloud gateway 源碼講解(一)

spring cloud gateway的核心類DispatcherHandler 這個類就和springmvc的dispatcherHandler的地位是一樣的,所有的請求都會經(jīng)過他。他的主要方法是handler

@Override

public Mono handle(ServerWebExchange exchange) {

if (logger.isDebugEnabled()) {

ServerHttpRequest request = exchange.getRequest();

logger.debug("Processing " + request.getMethodValue() +" request for [" + request.getURI() +"]");

}

if (this.handlerMappings ==null) {

return Mono.error(HANDLER_NOT_FOUND_EXCEPTION);

}

return Flux.fromIterable(this.handlerMappings)

.concatMap(mapping -> mapping.getHandler(exchange))

.next()

.switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION))

.flatMap(handler -> invokeHandler(exchange, handler))

.flatMap(result -> handleResult(exchange, result));

}

這是核心的代碼,因?yàn)閟pring cloud gateway 采用webflux+reactor的響應(yīng)式編程的方式,所以他的代碼就一行

下面將這一行代碼進(jìn)行分析:

一. 關(guān)鍵代碼getHandler()

1.?Flux.fromIterable(this.handlerMappings) 是獲取一個handlerMapping的集合,然后對這個集合進(jìn)行輪訓(xùn)處理

2.mapping.getHandler(exchange)這里面調(diào)用了getHandlerInternal(該方法是RoutePredicateHandlerMapping類下面的)這個就是調(diào)用了getHandlerInternal將路由放到了請求的上下文中,然后解決了跨域的問題關(guān)鍵代碼:

public Mono getHandler(ServerWebExchange exchange) {

return getHandlerInternal(exchange).map(handler -> {

if (CorsUtils.isCorsRequest(exchange.getRequest())) {

CorsConfiguration configA =this.globalCorsConfigSource.getCorsConfiguration(exchange);

CorsConfiguration configB = getCorsConfiguration(handler,exchange);

CorsConfiguration config = (configA !=null ? configA.combine(configB) : configB);

if (!getCorsProcessor().process(config,exchange) ||

CorsUtils.isPreFlightRequest(exchange.getRequest())) {

return REQUEST_HANDLED_HANDLER;

}

}

return handler;

});

}

3.getHandlerInternal()方法解析:這里面的代碼也是一行搞定的,關(guān)鍵的是lookupRoute()方法,這個方法顧名思義,是尋找路由的。這個方法就是將lookupRoute()過濾出來的route放到了exchange的GATEWAY_ROUTE_ATTR(請求的上下文中)

protected Mono getHandlerInternal(ServerWebExchange exchange) {

exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getClass().getSimpleName());

return lookupRoute(exchange)

// .log("route-predicate-handler-mapping", Level.FINER) //name this

? ? ? ? .flatMap((Function>) r -> {

if (logger.isDebugEnabled()) {

logger.debug("Mapping [" + getExchangeDesc(exchange) +"] to " + r);

}

exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);

return Mono.just(webHandler);

}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {

if (logger.isTraceEnabled()) {

logger.trace("No RouteDefinition found for [" + getExchangeDesc(exchange) +"]");

}

})));

}

4..lookupRoute()方法又調(diào)用了RouteDefinitionRouteLocator 里面的getRoutes方法,通過getRoutes獲取配置的所有的route之后,獲取其中的predicate和請求exchange中的路徑進(jìn)行匹配,看那個滿足predicate

protected Mono lookupRoute(ServerWebExchange exchange) {

return this.routeLocator.getRoutes()

.filter(route -> route.getPredicate().test(exchange))

// .defaultIfEmpty() put a static Route not found

// or .switchIfEmpty()

// .switchIfEmpty(Mono.empty().log("noroute"))

? ? ? ? .next()

//TODO: error handling

? ? ? ? .map(route -> {

if (logger.isDebugEnabled()) {

logger.debug("Route matched: " + route.getId());

}

validateRoute(route,exchange);

return route;

});

/* TODO: trace logging

if (logger.isTraceEnabled()) {

logger.trace("RouteDefinition did not match: " + routeDefinition.getId());

}*/

}

5.getRoutes()方法又調(diào)用了RouteDefinitionRouteLocator 里面的getRouteDefinitions方法,然后把獲取到router使用convertToRoute方法進(jìn)行過濾,convertToRoute方法就是對路由中predicate 和filter做了處理,重新生成了一個router,這個方法就是將配置文件中配置的router封裝了一個router對象的集合返回。

public Flux getRoutes() {

return this.routeDefinitionLocator.getRouteDefinitions()

.map(this::convertToRoute)

//TODO: error handling

? ? ? ? .map(route -> {

if (logger.isDebugEnabled()) {

logger.debug("RouteDefinition matched: " + route.getId());

}

return route;

});

/* TODO: trace logging

if (logger.isTraceEnabled()) {

logger.trace("RouteDefinition did not match: " + routeDefinition.getId());

}*/

}

////////////////////////////////

private Route convertToRoute(RouteDefinition routeDefinition) {

Predicate predicate = combinePredicates(routeDefinition);

List gatewayFilters = getFilters(routeDefinition);

return Route.builder(routeDefinition)

.predicate(predicate)

.gatewayFilters(gatewayFilters)

.build();

}

6.getRoutes的關(guān)鍵是PropertiesRouteDefinitionLocator的getRouteDefinitions這個方法其實(shí)就是從配置文件中獲取,我們在自動加載的配置文件的內(nèi)容

public Flux getRouteDefinitions() {

return Flux.fromIterable(this.properties.getRoutes());

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容