本系列代码地址:https://github.com/JoJoTec/sp...

咱们持续剖析上一节提到的 WebHandler,通过将申请封装成 ServerWebExchange 的 HttpWebHandlerAdapter 之后,申请会通过 ExceptionHandlingWebHandler

全局 Web 解决异样处理器的接入点 - ExceptionHandlingWebHandler

之前有网友私信问过笔者,如何给 Spring Cloud Gateway 加全局异样处理器,其实和给基于 Spring-Flux 的异步 Web 服务加是一样的,都是通过实现并注册一个 WebExceptionHandler Bean

WebExceptionHandler.java

public interface WebExceptionHandler {    Mono<Void> handle(ServerWebExchange exchange, Throwable ex);}

这些 Bean,就是在 ExceptionHandlingWebHandler 被退出到整个申请解决链路中的:

ExceptionHandlingWebHandler.java

@Overridepublic Mono<Void> handle(ServerWebExchange exchange) {    Mono<Void> completion;    try {        //这里其实就是组装前面的链路,即调用前面的 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;}

从源码能够看出,这里将每个 WebExceptionHandler 作为 Mono 的异样解决 onErrorResume 退出了链路。onErrorResume 的意思是如果链路后面产生异样,则在这里捕捉住异样同时调用 handler.handle(exchange, ex) 进行解决,如果应用阻塞代码了解,就相当于:

try {    //后面的链路} catch(Throwable ex) {    return handler.handle(exchange, ex)}

这里咱们看到有多个 WebExceptionHandler,都会在链路前面追加 onErrorResume,其实就相当于:

completion.onErrorResume(ex -> webExceptionHandler1.handle(exchange, ex)).onErrorResume(ex -> webExceptionHandler2.handle(exchange, ex)).onErrorResume(ex -> webExceptionHandler3.handle(exchange, ex))...

转换成阻塞代码了解,其实就是:

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)            //如果还有就持续叠加        }    }}

当 WebExceptionHandler 能够解决这个异样的时候,他的 handle 办法会返回一个真正的响应,否则会返回异样,例如:

public class WebExceptionHandler1 implements WebExceptionHandler {    @Override    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {        //如果是 ResponseStatusException 则应用异样外面的响应码和 HTTP 头填充响应的响应码和 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)));            //返回响应实现            return response.setComplete();        }        //抛出异样,持续链路异样解决        return Mono.error(ex);    }}

转换成同步代码去了解其实就是:

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)));    //返回响应实现    return response.setComplete();}//抛出异样,持续链路异样解决throw ex;

如果大家想封装本人对立的谬误响应,能够通过实现这个接口进行实现。

DefaultWebFilterChain 的链路终点 - FilteringWebHandler

接下来进入 FilteringWebHandler,留神是 org.springframework.web.server.handler.FilteringWebHandler 而不是 Spring Cloud Gateway 的 org.springframework.cloud.gateway.handler.FilteringWebHandler。在这里,会将上下文中载入的 WebFilter 拼接成 DefaultWebFilterChain,而后调用其 filter 办法:

private final DefaultWebFilterChain chain;public FilteringWebHandler(WebHandler handler, List<WebFilter> filters) {    super(handler);    this.chain = new DefaultWebFilterChain(handler, filters);}@Overridepublic Mono<Void> handle(ServerWebExchange exchange) {    return this.chain.filter(exchange);}

Spring Cloud Gateway 的 FilteringWebHandler, 它是 Spring Cloud Gateway 的解决申请业务的终点。在这里咱们行将进入整个 Spring Cloud Gateway 的 Filter 链路,包含每个门路本人的 GatewayFilter 以及全局的 GlobalGatewayFilter,都是在这里开始被解决组装成残缺调用链路的。咱们前面还会提到

因为咱们的我的项目依赖中蕴含了 Spring Cloud Sleuth 以及 Prometheus 的依赖,所以咱们这里的 WebFilter 会包含三个:

  • org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter:增加 Prometheus 相干依赖之后,会有这个 MetricsWebFilter,用于记录申请解决耗时,采集相干指标。
  • org.springframework.cloud.sleuth.instrument.web.TraceWebFilter:增加 Spring Cloud Sleuth 相干依赖之后,会有这个 TraceWebFilter。
  • org.springframework.cloud.gateway.handler.predicate.WeightCalculatorWebFilter:Spring Cloud Gateway 路由权重相干配置性能相干实现类,这个咱们这里不关怀。

其具体流程,咱们在下一节中持续详细分析。

微信搜寻“我的编程喵”关注公众号,每日一刷,轻松晋升技术,斩获各种offer