如何自定义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
相关产品推荐
相关产品推荐

