springcloudgateway全局通用异常处理

     2022-04-02     679

关键词:

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


@ControllerAdvice
public class ConsoleExceptionHandler {

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

例如: ③ 处应用调用数据库异常,通过 @ControllerAdvice 包装异常请求响应给客户端
技术图片
但在微服务架构下, 例如 ② 处 网关调用业务微服务失败(转发失败、调用异常、转发失败),在应用设置的 @ControllerAdvice 将失效,因为流量根本没有转发到应用上处理。
技术图片
如上图: 模拟所有路由断言都不匹配 404 , 和 spring boot 默认保持一致的错误输出页面。 显然我们在网关同样配置 @ControllerAdvice 是不能解决问题,因为 spring cloud gateway 是基于 webflux 反应式编程。
技术图片
解决方法
默认处理流程
ExceptionHandlingWebHandler 作为 spring cloud gateway 最核心 WebHandler 的一部分会进行异常处理的过滤

public class ExceptionHandlingWebHandler extends WebHandlerDecorator {
    @Override
    public Mono<Void> handle(ServerWebExchange exchange) {
        Mono<Void> 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
技术图片

public class DefaultErrorWebExceptionHandler  {

    @Override
    protected RouterFunction<ServerResponse> 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
 * <p>
 * 网关异常通用处理器,只作用在webflux 环境下 , 优先级低于 {@link ResponseStatusExceptionHandler} 执行
 */
@Slf4j
@Order(-1)
@RequiredArgsConstructor
public class GlobalExceptionConfiguration implements ErrorWebExceptionHandler {
    private final ObjectMapper objectMapper;

    @Override
    public Mono<Void> 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]);
                    }
                }));
    }
}

总结
重写的 DefaultErrorWebExceptionHandler 优先级一定要小于内置 ResponseStatusExceptionHandler 经过它处理的获取对应错误类的 响应码
其他扩展 可以参考 SentinelBlockExceptionHandler sentinel 整合网关的处理,不过整体和默认的异常处理没有什么区别
基础环境说明:Spring Cloud Hoxton.SR4 & Spring Boot 2.3.0

在带弹簧休息的全局异常处理程序中使用通用异常类处理程序是一种好习惯吗?

】在带弹簧休息的全局异常处理程序中使用通用异常类处理程序是一种好习惯吗?【英文标题】:IsitgoodpracticetohaveGenericExceptionclasshandleringlobalexceptionhandlerwithspringrest?【发布时间】:2019-02-2220:36:30【问题描述】:我参考了几篇文... 查看详情

springcloudgateway过滤器精确控制异常返回(实战,控制http返回码和message字段)(代码片段)

...套源码):https://github.com/zq2599/blog_demos本篇概览前文《SpringCloudGateway过滤器精确控制异常返回(分析篇)》咱们阅读源码,了解到SpringCloudGateway是如何处理全局异常信息的,学了那么多理论,不免手痒想实战验证学 查看详情

springcloudgateway过滤器精确控制异常返回(实战,控制http返回码和message字段)(代码片段)

...套源码):https://github.com/zq2599/blog_demos本篇概览前文《SpringCloudGateway过滤器精确控制异常返回(分析篇)》咱们阅读源码,了解到SpringCloudGateway是如何处理全局异常信息的,学了那么多理论,不免手痒想实战验证学 查看详情

springcloudgateway修改responsebody全局过滤器

publicclassResponseBodyModifyGlobalFilterimplementsGlobalFilter,Ordered{@OverridepublicMono<Void>filter(ServerWebExchangeexchange,GatewayFilterChainchain){returnchain.filter(exchange.mutate().re 查看详情

springcloudgateway--全局过滤器(globalfilter)--作用/使用

​简介    SpringCloudGateway支持自定义过滤器,可以很灵活的进行请求或者响应的控制。    自定义过滤器的方法是实现GlobalFilter接口、实现Ordered接口。这两个接口的全路径为:org.springframework.cloud.gatewa... 查看详情

springcloudgateway-自定义异常处理(代码片段)

前提我们平时在用SpringMVC的时候,只要是经过DispatcherServlet处理的请求,可以通过@ControllerAdvice和@ExceptionHandler自定义不同类型异常的处理逻辑,具体可以参考ResponseEntityExceptionHandler和DefaultHandlerExceptionResolver,底层原理很简单,... 查看详情

spring--springboot配置全局异常处理器

一、为什么要使用全局异常处理器?什么是全局异常处理器?就是把错误异常统一处理的方法。应用场景:1、当你使用jsr303参数校验器,如果参数校验不通过会抛异常,而且无法使用try-catch语句直接捕获,这时可以使用全局异... 查看详情

springcloud升级之路2020.0.x版-41.springcloudgateway基本流程讲解(代码片段)

...ceptionHandlingWebHandler之前有网友私信问过笔者,如何给SpringCloudGateway加全局异常处理器,其实和给基于Spring-Flux的异步Web服务加是一样的,都是通过实现并注册一个WebExceptionHandlerBean:WebExceptionHandler.javapublicinterfaceWe... 查看详情

重学springboot系列之统一全局异常处理(代码片段)

重学SpringBoot系列之统一全局异常处理设计一个优秀的异常处理机制异常处理的乱象例举该如何设计异常处理开发规范自定义异常和相关数据结构该如何设计数据结构枚举异常的类型自定义异常请求接口统一响应数据结构使用示... 查看详情

springcloudgateway—网关

7.全局过滤器该接口具有与相同的签名。这些是有条件地应用于所有路由的特殊过滤器。​​GlobalFilter​​​​GatewayFilter​​此接口及其用法可能会在未来的里程碑版本中发生变化。7.1.全局过滤器和网关过滤器的组合排序当请... 查看详情

任何异常的全局错误处理程序

】任何异常的全局错误处理程序【英文标题】:Globalerrorhandlerforanyexception【发布时间】:2015-06-0215:11:33【问题描述】:有没有办法添加一个全局包罗万象的错误处理程序,我可以在其中将响应更改为通用JSON响应?我不能使用got_r... 查看详情

springcloudgateway过滤器精确控制异常返回(分析篇)(代码片段)

...配套源码):https://github.com/zq2599/blog_demos本篇概览在《SpringCloudGateway修改请求和响应body的内容》一文中,咱们通过filter成功修改请求body的内容,当时留下个问题:在filter中如果发生异常(例如请求 查看详情

springcloudgateway过滤器精确控制异常返回(分析篇)(代码片段)

...配套源码):https://github.com/zq2599/blog_demos本篇概览在《SpringCloudGateway修改请求和响应body的内容》一文中,咱们通过filter成功修改请求body的内容,当时留下个问题:在filter中如果发生异常(例如请求 查看详情

JSF 1.x 通用异常处理

...接bean中的SQL异常),我如何通过自定义消息将其传播到全局error.jsp页面?【问题讨论】:【参考方案1】:JSF1.x不提供这种类型的任何隐式错误处理,尽管您可以使用导航规则重定向到错误页面(假设是表单发布)...< 查看详情

springcloudgateway过滤器精确控制异常返回(实战,完全定制返回body)(代码片段)

...(含配套源码):https://github.com/zq2599/blog_demos本篇概览SpringCloudGateway应用中,处理请求时若发生异常未被捕获,请求方收到的响应是系统默认的内容,无法满足实际业务需求因此,从前一篇文章《SpringCloudGatew 查看详情

springcloudgateway过滤器精确控制异常返回(实战,完全定制返回body)(代码片段)

...(含配套源码):https://github.com/zq2599/blog_demos本篇概览SpringCloudGateway应用中,处理请求时若发生异常未被捕获,请求方收到的响应是系统默认的内容,无法满足实际业务需求因此,从前一篇文章《SpringCloudGatew 查看详情

springcloudgateway限制文件上传大小

参考技术A公司使用springcloudgateway做为各个服务的入口,最近新接上传功能需求,需要限制文件上传的大小。所有请求某个请求org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory//1处根据请求头的content-length判断当前请... 查看详情

springcloudgateway并发问题:java.lang.nullpointerexception:null

问题描述基于springcloudgateway做的网关服务在运行一段时间后会报NullPointerException异常。异常日志如下:2022-03-1115:06:37.933ERROR1---[DiscoveryClient-CacheRefreshExecutor-0]com.netflix.discovery.DiscoveryClient:Cannotfetchreg 查看详情