Spring Gateway 中异常必须通过 Mono.error() 或 Flux.error() 主动抛出才能被 DefaultErrorWebExceptionHandler 捕获;需继承 AbstractErrorWebExceptionHandler 自定义处理器并注册为 Bean,优先级设为 Ordered.HIGHEST_PRECEDENCE + 1,统一处理 BusinessException 等类型返回结构化 JSON。

Spring Gateway 默认使用 DefaultErrorWebExceptionHandler 处理全局异常,但它**不直接捕获业务代码中 throw 的异常**——因为网关是响应式(Reactor)模型,throw 出的异常必须以 Mono/Flux 的错误信号(error signal)形式传播,才能被网关的异常处理器感知。
确保异常能被 DefaultErrorWebExceptionHandler 捕获
在 Spring Gateway 中,只有通过 WebFlux 的响应式链路抛出的异常才会进入全局错误处理器。普通 throw new RuntimeException() 在非响应式上下文中会被忽略或导致 500 响应但不走自定义逻辑。
- 在
GlobalFilter、GatewayFilter或路由断言/过滤器中,必须用Mono.error(...)或Flux.error(...)主动终止流并传递异常 - 避免在 lambda 或同步方法里直接
throw,否则异常会“掉出”响应式链路 - 示例正确写法:
Mono<Void> filter = exchange.getPrincipal()
.switchIfEmpty(Mono.error(new UnauthorizedException("Token missing")))
.flatMap(principal -> {
if (!isValid(principal)) {
return Mono.error(new ForbiddenException("Invalid token"));
}
return Mono.empty();
});
继承并重写 DefaultErrorWebExceptionHandler
Spring Boot 2.3+ 后,DefaultErrorWebExceptionHandler 不再允许直接配置,需通过自定义 WebExceptionHandler Bean 替换默认实现。
- 创建新类继承
AbstractErrorWebExceptionHandler(不是DefaultErrorWebExceptionHandler,后者已封装且不可直接继承) - 重写
writeError方法,在其中构造你想要的 JSON 结构(如{"code": 401, "message": "Unauthorized", "path": "/api/user"}) - 在构造函数中注入
ErrorAttributes和ResourceProperties等必要依赖
注册自定义异常处理器 Bean
通过 @Bean 提供一个 WebExceptionHandler,Spring Boot 会自动优先使用它。
立即学习“Java免费学习笔记(深入)”;
- 需指定
order = Ordered.HIGHEST_PRECEDENCE + 1,确保它比默认处理器优先级更高 - 在构造中传入自定义的
ErrorAttributes实现(可选),用于统一提取异常信息 - 关键点:不要试图修改
DefaultErrorWebExceptionHandler的内部行为,而是完全替代它
统一处理业务异常类型
建议定义自己的异常基类(如 BusinessException),并在 writeError 中做类型判断,返回差异化结构:
-
instanceof BusinessException→ 返回{"code": ex.getErrorCode(), "msg": ex.getMessage()} -
instanceof NotFoundException→ 映射为 404 并填充业务码 - 其他未识别异常 → 默认返回 500 + 友好提示(生产环境建议隐藏堆栈)


















