You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring自定义异常处理器调用正常,但返回结果被覆盖问题排查

排查思路
  • 检查WebClient异步处理与超时配置
    WebClient是异步调用,先确认异常转换的时机是否正确:如果用反应式编程返回Mono/Flux,必须用onErrorMap把WebClientRequestException转换成MyAppException,不能在回调里手动抛出(脱离Spring异常处理链);如果用block()同步调用,要确保异常能被Spring的拦截器捕获。另外对比容器(如Tomcat)的server.connection-timeout和WebClient的responseTimeout:如果容器超时更短,会先返回504,此时你的异常处理逻辑虽执行,但响应已被容器发送。

  • 验证异常处理器的优先级
    检查是否有其他@ControllerAdvice处理器或ErrorController实现类,它们的优先级可能比你的自定义处理器高,覆盖了响应。给你的ControllerExceptionHandler加上@Order(Ordered.HIGHEST_PRECEDENCE),确保它最先执行。同时排查是否存在第三方框架的异常处理器(比如Spring Security的异常处理),是否会拦截并修改响应。

  • 排查网关/代理的超时拦截
    如果服务前有网关(Spring Cloud Gateway、Nginx等),直接绕过网关访问服务实例:如果此时能返回自定义的500响应,说明网关的超时配置(如Nginx的proxy_read_timeout)过短,提前返回了504;如果还是返回504,再排查服务内部。

  • 检查Reactor流中的异常传播
    在反应式场景下,异常必须在Reactor流中正确传播。比如确保你的WebClient调用链是:

    webClient.get()
             .uri("/external-api")
             .retrieve()
             .bodyToMono(YourDto.class)
             .onErrorMap(WebClientRequestException.class, e -> new MyAppException("服务下线", e));
    

    而不是用try-catch包裹block(),后者可能导致异常被抛到非Spring管理的线程,无法被@ControllerAdvice正确处理(虽然你说处理器被调用了,但仍需确认流的完整性)。

  • 排查容器与Spring Boot的错误响应配置
    检查Spring Boot的server.error.*配置,比如server.error.path、server.error.whitelabel.enabled,是否启用了默认错误页面覆盖自定义响应。可以临时设置server.error.whitelabel.enabled=false,或者添加server.error.include-exception=true,看是否能看到自定义响应的内容。另外检查Tomcat等容器是否配置了自定义错误页面,是否会拦截500响应并替换为504。

  • 抓包验证实际响应
    用curl或Wireshark抓包,直接请求服务实例,看服务实际发送的响应状态码和内容:

    • 如果抓包显示服务返回500,但客户端收到504,问题出在中间代理/网关;
    • 如果抓包显示服务返回504,说明你的异常处理器返回的ResponseEntity被内部逻辑覆盖,需要调试Spring的响应处理链(比如在DispatcherServlet或ExceptionHandlerExceptionResolver加断点)。

内容的提问来源于stack exchange,提问作者wxkevin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 18:50:09