最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
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
注意限流、断路器等组件的异常穿透问题
像 RequestRateLimiter 或 Spring Cloud CircuitBreaker 抛出的异常,默认不会进入 GlobalFilter 的 onErrorResume,因为它们是在独立过滤器中完成的。要统一处理,有两种方式:
立即学习“Java免费学习笔记(深入)”;
- 在配置中显式指定回退逻辑,例如限流失败时返回自定义响应体(需配合
redis-rate-limiter的denyEmptyResponse和自定义RateLimiter实现) - 让这些组件抛出标准
ResponseStatusException(如new ResponseStatusException(HttpStatus.TOO_MANY_REQUESTS)),这样能被ErrorWebExceptionHandler统一接管 - 不建议在
GlobalFilter中尝试重写限流过滤器逻辑,容易破坏原有执行顺序和状态一致性
不要用 @ControllerAdvice
该注解依赖 Spring MVC 的同步请求上下文,在 WebFlux 响应式网关中完全无效。网关没有 Controller 层,也不经过 DispatcherHandler 的异常处理流程。试图添加 @RestControllerAdvice 不会产生任何效果。