一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Java中 WebFilter 响应式网关怎么捕获全局 Gateway 路由异常

时间:2026-07-21 09:18:48 编辑:袖梨 来源:一聚教程网

Spring Cloud Gateway 全局异常捕获仅支持 ErrorWebExceptionHandler(框架级兜底)和 GlobalFilter(链路级拦截)两类方式,前者推荐用于统一处理路由异常,后者适用于前置校验或转发后异常捕获,而 @ControllerAdvice 在 WebFlux 环境中无效。

Spring Cloud Gateway 是基于 WebFlux 的响应式网关,不走 Servlet 容器的 Filter 链,所以传统 javax.servlet.Filter 无法捕获其路由异常。真正有效的全局异常捕获方式只有两类:基于 ErrorWebExceptionHandler 的框架级兜底,或基于 GlobalFilter 的链路级拦截。两者定位不同,需按需选用。

用 ErrorWebExceptionHandler 替换默认错误处理器

这是最推荐的全局兜底方案,能捕获所有未被上游过滤器处理的异常(包括路由匹配失败、转发超时、下游服务不可达、限流触发等),且优先级高于默认实现。

  • 实现 ErrorWebExceptionHandler 接口,重写 handle() 方法
  • 加上 @Component@Order(-1) 确保它被 Spring Boot 优先加载
  • 检查 response.isCommitted(),避免重复写入已提交的响应
  • 统一构造 JSON 响应体(如 {"code":500,"message":"服务暂时不可用"}),设置 Content-Type: application/json
  • 对常见异常分类处理:比如 ResponseStatusException 取状态码,TimeoutException 返回 504,ConnectException 返回 503

用 GlobalFilter 拦截并提前终止异常链

适合在请求进入路由前做校验(如鉴权、参数校验),或在路由执行后捕获转发过程中的异常。注意它不能捕获网关内部组件(如断路器、限流器)抛出的原始异常,除非这些组件显式抛出并被链路传递。

  • 实现 GlobalFilter,用 @Order(-2) 确保早于路由过滤器执行
  • chain.filter(exchange).onErrorResume(...) 中捕获异常
  • 区分异常类型:若为 ResponseStatusException,直接设对应状态码;否则设 500 并记录日志
  • 调用 exchange.getResponse().setComplete() 终止后续过滤器执行
  • 避免在 onErrorResume 中抛出新异常,否则会再次触发 ErrorWebExceptionHandler

注意限流、断路器等组件的异常穿透问题

RequestRateLimiterSpring Cloud CircuitBreaker 抛出的异常,默认不会进入 GlobalFilteronErrorResume,因为它们是在独立过滤器中完成的。要统一处理,有两种方式:

立即学习“Java免费学习笔记(深入)”;

  • 在配置中显式指定回退逻辑,例如限流失败时返回自定义响应体(需配合 redis-rate-limiterdenyEmptyResponse 和自定义 RateLimiter 实现)
  • 让这些组件抛出标准 ResponseStatusException(如 new ResponseStatusException(HttpStatus.TOO_MANY_REQUESTS)),这样能被 ErrorWebExceptionHandler 统一接管
  • 不建议在 GlobalFilter 中尝试重写限流过滤器逻辑,容易破坏原有执行顺序和状态一致性

不要用 @ControllerAdvice

该注解依赖 Spring MVC 的同步请求上下文,在 WebFlux 响应式网关中完全无效。网关没有 Controller 层,也不经过 DispatcherHandler 的异常处理流程。试图添加 @RestControllerAdvice 不会产生任何效果。

热门栏目