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

如何自定义Spring Cloud Gateway自定义异常对应的响应状态码

网关自定义异常差异化设置状态码方案

针对网关自定义异常时无法区分设置状态码的问题,可通过自定义全局异常处理器实现,以下为Spring Cloud Gateway场景的实现步骤:

1. 先定义异常与状态码的映射规则(可选,方便后期维护)

可以用枚举类统一管理所有异常对应的状态码和提示信息:

public enum GatewayErrorEnum {
    AUTH_FAIL(401, "身份校验失败"),
    PERMISSION_DENY(403, "无接口访问权限"),
    SERVICE_DOWN(503, "下游服务暂不可用"),
    REQ_TIMEOUT(504, "网关请求超时"),
    SYS_ERROR(500, "网关内部错误");

    private final int statusCode;
    private final String errorMsg;

    GatewayErrorEnum(int statusCode, String errorMsg) {
        this.statusCode = statusCode;
        this.errorMsg = errorMsg;
    }

    public int getStatusCode() {
        return statusCode;
    }

    public String getErrorMsg() {
        return errorMsg;
    }
}

2. 实现全局异常处理器

自定义异常处理器优先级要高于网关默认的异常处理器,在处理器中根据异常类型匹配对应的状态码:

@Component
@Order(-1) // 优先级高于默认的DefaultErrorWebExceptionHandler
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        ServerHttpResponse response = exchange.getResponse();
        // 响应已提交的情况下直接抛出异常,避免重复写入
        if (response.isCommitted()) {
            return Mono.error(ex);
        }
        // 设置响应格式为JSON
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        HttpStatus httpStatus;
        String errorMsg;
        // 匹配不同异常类型设置对应状态码
        if (ex instanceof AuthenticationException) {
            httpStatus = HttpStatus.UNAUTHORIZED;
            errorMsg = GatewayErrorEnum.AUTH_FAIL.getErrorMsg();
        } else if (ex instanceof AccessDeniedException) {
            httpStatus = HttpStatus.FORBIDDEN;
            errorMsg = GatewayErrorEnum.PERMISSION_DENY.getErrorMsg();
        } else if (ex instanceof TimeoutException) {
            httpStatus = HttpStatus.GATEWAY_TIMEOUT;
            errorMsg = GatewayErrorEnum.REQ_TIMEOUT.getErrorMsg();
        } else if (ex instanceof ConnectException) {
            httpStatus = HttpStatus.SERVICE_UNAVAILABLE;
            errorMsg = GatewayErrorEnum.SERVICE_DOWN.getErrorMsg();
        } else {
            // 未匹配到的异常默认返回500
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
            errorMsg = GatewayErrorEnum.SYS_ERROR.getErrorMsg();
        }
        // 写入状态码
        response.setStatusCode(httpStatus);
        // 构造响应体
        Map<String, Object> result = new HashMap<>();
        result.put("code", httpStatus.value());
        result.put("msg", errorMsg);
        // 将响应写回客户端
        DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONBytes(result));
        return response.writeWith(Mono.just(dataBuffer));
    }
}

3. 自定义业务异常的处理

如果是你自己定义的业务异常类,可以直接在异常类里加statusCode字段,抛出异常时传入对应状态码,在异常处理器中直接取出该字段设置为响应状态码即可:

// 自定义业务异常类示例
public class BizGatewayException extends RuntimeException{
    private int statusCode;
    public BizGatewayException(int statusCode, String msg) {
        super(msg);
        this.statusCode = statusCode;
    }
    public int getStatusCode() {
        return statusCode;
    }
}
// 异常处理器中添加判断逻辑
if (ex instanceof BizGatewayException bizEx) {
    httpStatus = HttpStatus.valueOf(bizEx.getStatusCode());
    errorMsg = bizEx.getMessage();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 18:45:03