Spring Cloud Gateway 全局异常捕获仅支持 ErrorWebExceptionHandler(框架级兜底)和 GlobalFilter(链路级拦截)两类方式,前者推荐用于统一处理路由异常,后者适用于前置校验或转发后异常捕获,而 @ControllerAdvice 在 WebFlux 环境中无效。
Spring Cloud Gateway 是基于 WebFlux 的响应式网关,不走 Servlet 容器的 Filter 链,所以传统 javax.servlet.Filter 无法捕获其路由异常。真正有效的全局异常捕获方式只有两类:基于 ErrorWebExceptionHandler 的框架级兜底,或基于 GlobalFilter 的链路级拦截。两者定位不同,需按需选用。
这是最推荐的全局兜底方案,能捕获所有未被上游过滤器处理的异常(包括路由匹配失败、转发超时、下游服务不可达、限流触发等),且优先级高于默认实现。
ErrorWebExceptionHandler 接口,重写 handle() 方法@Component 和 @Order(-1) 确保它被 Spring Boot 优先加载response.isCommitted(),避免重复写入已提交的响应{"code":500,"message":"服务暂时不可用"}),设置 Content-Type: application/json
ResponseStatusException 取状态码,TimeoutException 返回 504,ConnectException 返回 503适合在请求进入路由前做校验(如鉴权、参数校验),或在路由执行后捕获转发过程中的异常。注意它不能捕获网关内部组件(如断路器、限流器)抛出的原始异常,除非这些组件显式抛出并被链路传递。
GlobalFilter,用 @Order(-2) 确保早于路由过滤器执行chain.filter(exchange).onErrorResume(...) 中捕获异常ResponseStatusException,直接设对应状态码;否则设 500 并记录日志exchange.getResponse().setComplete() 终止后续过滤器执行onErrorResume 中抛出新异常,否则会再次触发 ErrorWebExceptionHandler
像 RequestRateLimiter 或 Spring Cloud CircuitBreaker 抛出的异常,默认不会进入 GlobalFilter 的 onErrorResume,因为它们是在独立过滤器中完成的。要统一处理,有两种方式:
立即学习“Java免费学习笔记(深入)”;
redis-rate-limiter 的 denyEmptyResponse 和自定义 RateLimiter 实现)ResponseStatusException(如 new ResponseStatusException(HttpStatus.TOO_MANY_REQUESTS)),这样能被 ErrorWebExceptionHandler 统一接管GlobalFilter 中尝试重写限流过滤器逻辑,容易破坏原有执行顺序和状态一致性该注解依赖 Spring MVC 的同步请求上下文,在 WebFlux 响应式网关中完全无效。网关没有 Controller 层,也不经过 DispatcherHandler 的异常处理流程。试图添加 @RestControllerAdvice 不会产生任何效果。