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

@RestControllerAdvice搭配@ResponseStatus时前端无异常响应问题

问题背景
  • 项目中使用@RestControllerAdvice实现全局异常处理,逻辑为根据抛出的运行时异常类型返回对应的自定义响应。
  • 本地调试、Postman发起请求时功能运行完全正常,但部署到Quality环境后,异常触发时前端无法接收到任何响应,Postman发起完全相同的请求却可正常获取返回结果。
  • 经过约5小时排查,移除异常处理方法上的@ResponseStatus注解后,异常发生时前端即可正常接收响应。
  • 存在问题的@RestControllerAdvice实现代码如下:
@RestControllerAdvice
public class SftpExceptionHandler {

    @ExceptionHandler(FileTypeNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public GeneralResponse handlerRequestException(FileTypeNotFoundException ex) {
        return new GeneralResponse(HttpStatus.NOT_FOUND, ex.getMessage());
    }

    @ExceptionHandler(IncorrectConsecutiveException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public GeneralResponse handlerRequestException(IncorrectConsecutiveException ex) {
        return new GeneralResponse(HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage());
    }

    @ExceptionHandler(InvalidBinaryFileException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public GeneralResponse handlerRequestException(InvalidBinaryFileException ex) {
        return new GeneralResponse(HttpStatus.BAD_REQUEST, ex.getMessage());
    }

}
  • 自定义异常示例代码如下:
public class InvalidBinaryFileException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    public InvalidBinaryFileException(String message) {
        super(message);
    }
}
问题原因

该问题是环境链路差异+@ResponseStatus底层生效逻辑共同导致的:

  • @ResponseStatus的核心作用是标记方法对应的HTTP响应状态码,Spring处理完该方法返回值后,不仅会把对应状态码写入响应头,还会向Servlet容器发起标准错误请求派发(即走Servlet的error dispatch流程)。
  • 本地调试、Postman直连后端服务测试时,请求不经过中间代理层,即使触发了错误派发,容器最终还是会将GeneralResponse响应体正常返回,因此表现完全正常。
  • Quality环境的前端调用链路一般会额外部署Nginx/API网关这类反向代理层,这类代理默认配置了错误拦截规则:只要检测到后端返回的响应走了错误派发流程、状态码为4xx/5xx,就会直接丢弃后端原始返回的响应体,要么返回网关预置的空白错误页,要么直接中断连接,前端自然收不到任何响应内容。
  • Postman可以正常获取结果,基本都是因为测试时Postman请求的是后端服务直连地址,没有走前端访问时经过的网关层,不会触发拦截规则。
修复方案
  • 直接移除异常处理方法上的@ResponseStatus注解即可。此时返回的GeneralResponse会作为正常响应体返回,不会触发Servlet容器的错误派发流程,网关不会执行拦截,前端即可正常拿到响应内容。如果项目规范是在响应体中封装业务状态码、HTTP层统一返回200,这种方式完全适配。
  • 如果需要让HTTP响应状态码和业务错误码保持对齐,不要使用@ResponseStatus注解,直接在方法内注入HttpServletResponse手动设置状态码即可,该方式不会触发错误派发流程:
@ExceptionHandler(InvalidBinaryFileException.class)
public GeneralResponse handlerRequestException(InvalidBinaryFileException ex, HttpServletResponse response) {
    response.setStatus(HttpStatus.BAD_REQUEST.value());
    return new GeneralResponse(HttpStatus.BAD_REQUEST, ex.getMessage());
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 16:36:43