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));

}

這是核心的代碼,因為spring 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這個方法其實就是從配置文件中獲取纤子,我們在自動加載的配置文件的內(nèi)容

public Flux getRouteDefinitions() {

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

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末搬瑰,一起剝皮案震驚了整個濱河市款票,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌泽论,老刑警劉巖徽职,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異佩厚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)说订,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門抄瓦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人陶冷,你說我怎么就攤上這事钙姊。” “怎么了埂伦?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵煞额,是天一觀的道長。 經(jīng)常有香客問我沾谜,道長膊毁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任基跑,我火速辦了婚禮婚温,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘媳否。我一直安慰自己栅螟,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布篱竭。 她就那樣靜靜地躺著力图,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掺逼。 梳的紋絲不亂的頭發(fā)上吃媒,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機(jī)與錄音吕喘,去河邊找鬼晓折。 笑死,一個胖子當(dāng)著我的面吹牛兽泄,可吹牛的內(nèi)容都是我干的漓概。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼病梢,長吁一口氣:“原來是場噩夢啊……” “哼胃珍!你這毒婦竟也來了梁肿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤觅彰,失蹤者是張志新(化名)和其女友劉穎吩蔑,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體填抬,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡烛芬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了飒责。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赘娄。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖宏蛉,靈堂內(nèi)的尸體忽然破棺而出遣臼,到底是詐尸還是另有隱情,我是刑警寧澤拾并,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布揍堰,位于F島的核電站,受9級特大地震影響嗅义,放射性物質(zhì)發(fā)生泄漏屏歹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一之碗、第九天 我趴在偏房一處隱蔽的房頂上張望西采。 院中可真熱鬧,春花似錦继控、人聲如沸械馆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽霹崎。三九已至,卻和暖如春冶忱,著一層夾襖步出監(jiān)牢的瞬間尾菇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工囚枪, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留派诬,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓链沼,卻偏偏與公主長得像默赂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子括勺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354