摘要:在這里,會(huì)將上下文中載入的拼接成,然后調(diào)用其方法的,它是的處理請(qǐng)求業(yè)務(wù)的起點(diǎn)。添加相關(guān)依賴之后,會(huì)有這個(gè)。路由權(quán)重相關(guān)配置功能相關(guān)實(shí)現(xiàn)類,這個(gè)我們這里不關(guān)心。
我們繼續(xù)分析上一節(jié)提到的 WebHandler
,經(jīng)過(guò)將請(qǐng)求封裝成 ServerWebExchange 的 HttpWebHandlerAdapter 之后,請(qǐng)求會(huì)經(jīng)過(guò) ExceptionHandlingWebHandler
之前有網(wǎng)友私信問(wèn)過(guò)筆者,如何給 Spring Cloud Gateway 加全局異常處理器,其實(shí)和給基于 Spring-Flux 的異步 Web 服務(wù)加是一樣的,都是通過(guò)實(shí)現(xiàn)并注冊(cè)一個(gè) WebExceptionHandler
Bean:
public interface WebExceptionHandler { Mono handle(ServerWebExchange exchange, Throwable ex);}
這些 Bean,就是在 ExceptionHandlingWebHandler 被加入到整個(gè)請(qǐng)求處理鏈路中的:
ExceptionHandlingWebHandler.java
@Overridepublic Mono handle(ServerWebExchange exchange) { Mono completion; try { //這里其實(shí)就是組裝后面的鏈路,即調(diào)用后面的 FilteringWebHandler 的 handle completion = super.handle(exchange); } catch (Throwable ex) { completion = Mono.error(ex); } for (WebExceptionHandler handler : this.exceptionHandlers) { completion = completion.onErrorResume(ex -> handler.handle(exchange, ex)); } return completion;}
從源碼可以看出,這里將每個(gè) WebExceptionHandler
作為 Mono 的異常處理 onErrorResume
加入了鏈路。onErrorResume
的意思是如果鏈路前面發(fā)生異常,則在這里捕獲住異常同時(shí)調(diào)用 handler.handle(exchange, ex)
進(jìn)行處理,如果使用阻塞代碼理解,就相當(dāng)于:
try { //前面的鏈路} catch(Throwable ex) { return handler.handle(exchange, ex)}
這里我們看到有多個(gè) WebExceptionHandler
,都會(huì)在鏈路后面追加 onErrorResume
,其實(shí)就相當(dāng)于:
completion.onErrorResume(ex -> webExceptionHandler1.handle(exchange, ex)).onErrorResume(ex -> webExceptionHandler2.handle(exchange, ex)).onErrorResume(ex -> webExceptionHandler3.handle(exchange, ex))...
轉(zhuǎn)換成阻塞代碼理解,其實(shí)就是:
try { completion} catch(Throwable e1) { try { return webExceptionHandler1.handle(exchange, e1) } catch(Throwable e2) { try { return webExceptionHandler2.handle(exchange, ex) } catch(Throwable e2) { return webExceptionHandler3.handle(exchange, ex) //如果還有就繼續(xù)疊加 } }}
當(dāng) WebExceptionHandler 可以處理這個(gè)異常的時(shí)候,他的 handle
方法會(huì)返回一個(gè)真正的響應(yīng),否則會(huì)返回異常,例如:
public class WebExceptionHandler1 implements WebExceptionHandler { @Override public Mono handle(ServerWebExchange exchange, Throwable ex) { //如果是 ResponseStatusException 則使用異常里面的響應(yīng)碼和 HTTP 頭填充響應(yīng)的響應(yīng)碼和 HTTP 頭 if (ex instanceof ResponseStatusException) { ServerHttpResponse response = exchange.getResponse(); ResponseStatusException responseStatusException = (ResponseStatusException) ex; response.setRawStatusCode(responseStatusException.getRawStatusCode()); responseStatusException.getResponseHeaders() .forEach((name, values) -> values.forEach(value -> response.getHeaders().add(name, value))); //返回響應(yīng)完成 return response.setComplete(); } //拋出異常,繼續(xù)鏈路異常處理 return Mono.error(ex); }}
轉(zhuǎn)換成同步代碼去理解其實(shí)就是:
if (ex instanceof ResponseStatusException) { ServerHttpResponse response = exchange.getResponse(); ResponseStatusException responseStatusException = (ResponseStatusException) ex; response.setRawStatusCode(responseStatusException.getRawStatusCode()); responseStatusException.getResponseHeaders() .forEach((name, values) -> values.forEach(value -> response.getHeaders().add(name, value))); //返回響應(yīng)完成 return response.setComplete();}//拋出異常,繼續(xù)鏈路異常處理throw ex;
如果大家想封裝自己統(tǒng)一的錯(cuò)誤響應(yīng),可以通過(guò)實(shí)現(xiàn)這個(gè)接口進(jìn)行實(shí)現(xiàn)。
接下來(lái)進(jìn)入 FilteringWebHandler,注意是 org.springframework.web.server.handler.FilteringWebHandler
而不是 Spring Cloud Gateway 的 org.springframework.cloud.gateway.handler.FilteringWebHandler
。在這里,會(huì)將上下文中載入的 WebFilter 拼接成 DefaultWebFilterChain
,然后調(diào)用其 filter 方法:
private final DefaultWebFilterChain chain;public FilteringWebHandler(WebHandler handler, List filters) { super(handler); this.chain = new DefaultWebFilterChain(handler, filters);}@Overridepublic Mono handle(ServerWebExchange exchange) { return this.chain.filter(exchange);}
Spring Cloud Gateway 的 FilteringWebHandler, 它是 Spring Cloud Gateway 的處理請(qǐng)求業(yè)務(wù)的起點(diǎn)。在這里我們即將進(jìn)入整個(gè) Spring Cloud Gateway 的 Filter 鏈路,包括每個(gè)路徑自己的 GatewayFilter
以及全局的 GlobalGatewayFilter
,都是在這里開(kāi)始被處理組裝成完整調(diào)用鏈路的。我們后面還會(huì)提到
由于我們的項(xiàng)目依賴中包含了 Spring Cloud Sleuth 以及 Prometheus 的依賴,所以我們這里的 WebFilter 會(huì)包括三個(gè):
org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter
:添加 Prometheus 相關(guān)依賴之后,會(huì)有這個(gè) MetricsWebFilter,用于記錄請(qǐng)求處理耗時(shí),采集相關(guān)指標(biāo)。org.springframework.cloud.sleuth.instrument.web.TraceWebFilter
:添加 Spring Cloud Sleuth 相關(guān)依賴之后,會(huì)有這個(gè) TraceWebFilter。org.springframework.cloud.gateway.handler.predicate.WeightCalculatorWebFilter
:Spring Cloud Gateway 路由權(quán)重相關(guān)配置功能相關(guān)實(shí)現(xiàn)類,這個(gè)我們這里不關(guān)心。其具體流程,我們?cè)谙乱还?jié)中繼續(xù)詳細(xì)分析。
微信搜索“我的編程喵”關(guān)注公眾號(hào),每日一刷,輕松提升技術(shù),斬獲各種offer:
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/125367.html
摘要:在這里,會(huì)將上下文中載入的拼接成,然后調(diào)用其方法的,它是的處理請(qǐng)求業(yè)務(wù)的起點(diǎn)。添加相關(guān)依賴之后,會(huì)有這個(gè)。路由權(quán)重相關(guān)配置功能相關(guān)實(shí)現(xiàn)類,這個(gè)我們這里不關(guān)心。 本系列代碼地址:??https://github.com/JoJoTec/spring-cloud-parent??我們繼續(xù)分析上一節(jié)提到的 ??WebHandle...
摘要:將請(qǐng)求封裝成將請(qǐng)求封裝成的接口定義是但是最外層傳進(jìn)來(lái)的參數(shù)是和,需要將他們封裝成,這個(gè)工作就是在中做的。其實(shí)主要任務(wù)就是將各種參數(shù)封裝成除了和本次請(qǐng)求相關(guān)的和,還有會(huì)話管理器,編碼解碼器配置,國(guó)際化配置還有用于擴(kuò)展。本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent接下來(lái),將進(jìn)入我們升級(jí)之路的又一大模塊,即網(wǎng)關(guān)模塊。網(wǎng)關(guān)模塊我們廢棄了...
摘要:添加相關(guān)依賴之后,會(huì)有這個(gè)。接著,根據(jù)的源碼分析,會(huì)繼續(xù)鏈路,到達(dá)下一個(gè),即。在中,我們會(huì)計(jì)算出路由并發(fā)送請(qǐng)求到符合條件的。這個(gè)是的,會(huì)讀取配置并生成路由。本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent我們繼續(xù)分析上一節(jié)提到的 WebHandler。加入 Spring Cloud Sleuth 以及 Prometheus 相關(guān)依賴...
摘要:升級(jí)之路版基本流程講解抽象類本系列代碼地址我們繼續(xù)分析上一節(jié)提到的。添加相關(guān)依賴之后,會(huì)有這個(gè)。路由權(quán)重相關(guān)配置功能相關(guān)實(shí)現(xiàn)類,這個(gè)我們這里不關(guān)心。這個(gè)是的,會(huì)讀取配置并生成路由。 本系列代碼地址:??https://github.com/JoJoTec/spring-cloud-parent??我們繼續(xù)分析上一節(jié)提到的 ...
摘要:對(duì)于異步的請(qǐng)求,使用的是異步客戶端即。要實(shí)現(xiàn)的配置設(shè)計(jì)以及使用舉例要實(shí)現(xiàn)的配置設(shè)計(jì)以及使用舉例首先,我們要實(shí)現(xiàn)的,其包含三個(gè)重試重試的要在負(fù)載均衡之前,因?yàn)橹卦嚨臅r(shí)候,我們會(huì)從負(fù)載均衡器獲取另一個(gè)實(shí)例進(jìn)行重試,而不是在同一個(gè)實(shí)例上重試多次。 本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent 為何需要封裝異步 HT...
閱讀 3792·2023-01-11 11:02
閱讀 4299·2023-01-11 11:02
閱讀 3121·2023-01-11 11:02
閱讀 5231·2023-01-11 11:02
閱讀 4793·2023-01-11 11:02
閱讀 5568·2023-01-11 11:02
閱讀 5371·2023-01-11 11:02
閱讀 4070·2023-01-11 11:02