不建议在接口中直接用public static final常量定义共享错误码,应改用实现errorcode接口的枚举类分模块定义,并将通用错误码沉淀至无框架依赖的基础模块,配合自定义异常与全局处理器实现标准化响应。

不建议在接口中直接用 public static final 常量定义多个模块共享的标准错误码。
这种写法看似简洁,实则隐患明显:常量只存数字或字符串,没有语义绑定、无 HTTP 状态、无提示文案、无国际化支持;不同模块各自实现同一接口时,极易出现同码不同义(比如 1001 在用户服务表示“用户不存在”,在订单服务却代表“库存不足”);编译期无法校验字段含义一致性,运行时也难以追溯来源。
真正可行的共享方式,是把“接口常量”降级为轻量索引,而把标准错误码的权威定义、元数据承载和跨语言一致性交给更健壮的机制。
用枚举实现模块化、可扩展的错误码契约
定义统一接口,约束所有错误码必须提供基础能力:
public interface ErrorCode {
int code();
String message();
int httpStatus();
}
每个业务模块独立定义自己的枚举,实现该接口:
-
UserErrorCode(用户模块) -
OrderErrorCode(订单模块) -
PaymentErrorCode(支付模块)
枚举内部明确 code、提示语、HTTP 状态,例如:
public enum UserErrorCode implements ErrorCode {
USER_NOT_FOUND(1001, "用户不存在", 404),
USER_DISABLED(1002, "账号已被禁用", 403);
private final int code;
private final String message;
private final int httpStatus;
UserErrorCode(int code, String message, int httpStatus) {
this.code = code;
this.message = message;
this.httpStatus = httpStatus;
}
@Override public int code() { return code; }
@Override public String message() { return message; }
@Override public int httpStatus() { return httpStatus; }
}
好处是类型安全、IDE 可补全、可遍历、可单元测试断言,且各模块互不污染。
把公共错误码沉淀到基础模块,靠 static 初始化保障跨模块可用
将通用平台级错误码(如 SUCCESS(0)、SYSTEM_ERROR(50000)、AUTH_FAILED(40100))放在 common-core 这类无框架依赖的底层模块中:
- 模块
pom.xml不引入 Spring、Web、MyBatis 等任何业务依赖; - 使用
static {}块加载/error-codes.properties,构建不可变Map<string errorcode></string>; - 字段声明为
public static final Map<string errorcode> ALL</string>,并用Collections.unmodifiableMap()封装; - 加载失败直接抛
ExceptionInInitializerError,强制暴露配置问题。
这样,user-service 和 order-api 都能直接 import 并使用,不依赖 Spring 上下文,也不受启动顺序影响。
让错误码真正“活”起来:异常对象 + 全局处理器
自定义异常类持有 ErrorCode 枚举实例:
public class BusinessException extends RuntimeException {
private final ErrorCode errorCode;
public BusinessException(ErrorCode errorCode) {
super(errorCode.message());
this.errorCode = errorCode;
}
public int getCode() { return errorCode.code(); }
public int getHttpStatus() { return errorCode.httpStatus(); }
}
配合 @ControllerAdvice 统一拦截,输出标准 JSON 响应:
{ "code": 1001, "message": "用户不存在", "httpStatus": 404 }
日志中自动记录 errorCode.code(),前端根据 code 做精准提示,排查时一眼定位语义。
接口里的常量,只适合做极简别名或测试断言(如 assertThat(ex.getCode()).isEqualTo(UserErrorCode.USER_NOT_FOUND.code())),绝不该承担语义定义、跨系统映射或运行时转换的职责。标准化来自协议(如 Protobuf)、生成代码、运行时转换三者闭环,不是靠一个 interface 文件。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











