Java统一业务错误码的核心是建立“异常→错误码→响应体”标准化转换机制,需定义分层错误码枚举、继承BizException封装动态信息、通过@ControllerAdvice全局拦截并按类型映射响应,确保code唯一稳定且前端可识别。

Java 中将异常包装成统一的业务错误码,核心是建立“异常 → 错误码 → 响应体”的标准化转换机制,而不是在每个 catch 里硬编码返回。关键在于分层拦截、统一兜底、按需映射。
定义统一错误码枚举
先设计一个业务错误码枚举类,涵盖系统级、参数级、业务级等常见场景,每个枚举项包含 code、message、httpStatus(可选):
public enum BizErrorCode {
SUCCESS(0, "操作成功"),
PARAM_ERROR(1001, "参数校验失败"),
USER_NOT_FOUND(2001, "用户不存在"),
ORDER_LOCKED(3005, "订单已被锁定"),
SYSTEM_ERROR(5000, "系统繁忙,请稍后再试");
private final int code;
private final String message;
// 构造、getter 省略
}
建议按模块或严重程度分段编号(如 1xxx 参数类、2xxx 用户类、5xxx 系统类),便于排查和前端识别。
自定义业务异常类
所有业务逻辑中主动抛出的异常,都应继承自一个基类(如 BizException),并携带错误码枚举和可选的动态信息(如用户名、订单号):
立即学习“Java免费学习笔记(深入)”;
- 避免直接 throw new RuntimeException("xxx") —— 无法结构化提取错误码
- 推荐构造方式:
throw new BizException(BizErrorCode.USER_NOT_FOUND, "uid=12345") - BizException 内部持有
errorCode和args,message 可延迟格式化(如用 MessageFormat)
全局异常处理器统一拦截
用 @ControllerAdvice + @ExceptionHandler 拦截所有 Controller 层异常,按类型分别处理:
- 捕获 BizException:直接取其 error code 和填充后的 message,组装为标准响应(如
{ "code": 2001, "msg": "用户不存在", "data": null }) - 捕获 MethodArgumentNotValidException(参数校验失败):解析 BindingResult,映射为
PARAM_ERROR,并带上具体字段错误(如"username 不能为空") - 捕获 Throwable(兜底):记录日志 + 返回
SYSTEM_ERROR,绝不暴露堆栈给前端
非 Controller 场景也要保持一致
Service 或异步任务中抛出异常时,仍用 BizException;若需跨线程传递,确保异常对象可序列化。必要时通过 AOP 在关键 Service 方法上增强异常包装逻辑,但优先靠开发规范约束。
不复杂但容易忽略的是:前端调用方只认 code 字段做分支判断,所以错误码必须唯一、稳定、文档化,且禁止在不同业务中复用同一 code 表达不同语义。


















