如何实现SpringCloudGateway全局通用异常处理

小编这次要给大家分享的是如何实现Spring Cloud Gateway全局通用异常处理,文章内容丰富,感兴趣的小伙伴可以来了解一下,希望大家阅读完这篇文章之后能够有所收获。

创新互联公司主要从事成都网站建设、做网站、网页设计、企业做网站、公司建网站等业务。立足成都服务阜新,十年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:18982081108

为什么需要全局异常处理

在传统 Spring Boot 应用中, 我们 @ControllerAdvice 来处理全局的异常,进行统一包装返回

// 摘至 spring cloud alibaba console 模块处理
@ControllerAdvice
public class ConsoleExceptionHandler {

  @ExceptionHandler(AccessException.class)
  private ResponseEntity handleAccessException(AccessException e) {
    return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getErrMsg());
  }
}

例如: ③ 处应用调用数据库异常,通过 @ControllerAdvice 包装异常请求响应给客户端

如何实现Spring Cloud Gateway全局通用异常处理

但在微服务架构下, 例如 ② 处 网关调用业务微服务失败(转发失败、调用异常、转发失败),在应用设置的 @ControllerAdvice 将失效,因为流量根本没有转发到应用上处理。

如何实现Spring Cloud Gateway全局通用异常处理

如上图: 模拟所有路由断言都不匹配 404 , 和 spring boot 默认保持一致的错误输出页面。 显然我们在网关同样配置 @ControllerAdvice 是不能解决问题,因为 spring cloud gateway 是基于 webflux 反应式编程。

如何实现Spring Cloud Gateway全局通用异常处理

解决方法

默认处理流程

ExceptionHandlingWebHandler 作为 spring cloud gateway 最核心 WebHandler 的一部分会进行异常处理的过滤

public class ExceptionHandlingWebHandler extends WebHandlerDecorator {
  @Override
  public Mono handle(ServerWebExchange exchange) {
    Mono completion;
    try {
      completion = super.handle(exchange);
    }
    catch (Throwable ex) {
      completion = Mono.error(ex);
    }

   // 获取全局的 WebExceptionHandler 执行
    for (WebExceptionHandler handler : this.exceptionHandlers) {
      completion = completion.onErrorResume(ex -> handler.handle(exchange, ex));
    }
    return completion;
  }
}

默认实现 DefaultErrorWebExceptionHandler

如何实现Spring Cloud Gateway全局通用异常处理

public class DefaultErrorWebExceptionHandler {

  @Override
  protected RouterFunction getRoutingFunction(ErrorAttributes errorAttributes) {
   // 根据客户端 `accpet` 请求头决定返回什么资源,如上浏览器返回的是 页面
    return route(acceptsTextHtml(), this::renderErrorView).andRoute(all(), this::renderErrorResponse);
  }
}
// 模拟指定 `accpet` 情况
curl --location --request GET 'http://localhost:9999/adminx/xx' \ 18:09:23
   --header 'Accept: application/json'
{"timestamp":"2020-05-24 18:09:24","path":"/adminx/xx","status":404,"error":"Not Found","message":null,"requestId":"083c48e3-2"}⏎

重写 ErrorWebExceptionHandler

/**
 * @author lengleng
 * @date 2020/5/23
 * 

* 网关异常通用处理器,只作用在webflux 环境下 , 优先级低于 {@link ResponseStatusExceptionHandler} 执行 */ @Slf4j @Order(-1) @RequiredArgsConstructor public class GlobalExceptionConfiguration implements ErrorWebExceptionHandler { private final ObjectMapper objectMapper; @Override public Mono handle(ServerWebExchange exchange, Throwable ex) { ServerHttpResponse response = exchange.getResponse(); if (response.isCommitted()) { return Mono.error(ex); } // header set response.getHeaders().setContentType(MediaType.APPLICATION_JSON); if (ex instanceof ResponseStatusException) { response.setStatusCode(((ResponseStatusException) ex).getStatus()); } return response .writeWith(Mono.fromSupplier(() -> { DataBufferFactory bufferFactory = response.bufferFactory(); try { return bufferFactory.wrap(objectMapper.writeValueAsBytes(R.failed(ex.getMessage()))); } catch (JsonProcessingException e) { log.warn("Error writing response", ex); return bufferFactory.wrap(new byte[0]); } })); } }

看完这篇关于如何实现Spring Cloud Gateway全局通用异常处理的文章,如果觉得文章内容写得不错的话,可以把它分享出去给更多人看到。


本文名称:如何实现SpringCloudGateway全局通用异常处理
网页路径:http://ybzwz.com/article/jppjpp.html