错误码为字符串类型,共5位,分成两个部分:错误产生来源+四位数字编号。
说明:错误产生来源分为A/B/C
- A表示错误来源于用户,比如参数错误,用户安装版本过低,用户支付超时等问题;
- B表示错误来源于当前系统,往往是业务逻辑出错,或程序健壮性差等问题;
- C表示错误来源于第三方服务,比如CDN服务出错,消息投递超时等问题;
四位数字编号从0001到9999,大类之间的步长间距预留100。
编号不与公司业务架构,更不与组织架构挂钩,以先到先得的原则在统一平台上进行,审批生效,编号即被永久固定。
错误码分三级设置::一级宏观错误码、二级宏观错误码、三级详细错误码。
举例:
错误码 | 中文描述 | 说明 |
A0001 | 用户端错误 | 一级宏观错误码 |
A0100 | 用户注册错误 | 二级宏观错误码 |
A0101 | 用户未同意隐私协议 | 三级宏观错误码 |
A0102 | 注册国家或地区受限 | |
A0110 | 用户名校验失败 | |
A0111 | 用户名已存在 | |
A0112 | 用户名包含敏感词 | |
...... | ...... | ...... |
A0200 | 用户登录异常 | 二级宏观错误码 |
错误码 | 中文描述 | 说明 |
B0001 | 系统执行出错 | 一级宏观错误码 |
B0100 | 系统执行超时 | 二级宏观错误码 |
错误码 | 中文描述 | 说明 |
C0001 | 调用第三方服务出错 | 一级宏观错误码 |
C0100 | 中间件服务出错 | 二级宏观错误码 |
业务实践
通常,错误码枚举类均实现一接口类,主要是对异常码格式的规范:
public interface IErrorCode {
/**
* 错误码
*/
String code();
/**
* 错误信息
*/
String message();
}
异常码枚举类一般放在基建子模块下的 convention(规约)包下:
为了平台规范性和利于后期拓展,这里将异常码的位数拓展到了 7 位:
public enum BaseErrorCode implements IErrorCode {
// ========== 一级宏观错误码 客户端错误 ==========
CLIENT_ERROR("A000001", "用户端错误"),
// ========== 二级宏观错误码 用户注册错误 ==========
USER_REGISTER_ERROR("A000100", "用户注册错误"),
USER_NAME_VERIFY_ERROR("A000110", "用户名校验失败"),
USER_NAME_EXIST_ERROR("A000111", "用户名已存在"),
USER_NAME_SENSITIVE_ERROR("A000112", "用户名包含敏感词"),
USER_NAME_SPECIAL_CHARACTER_ERROR("A000113", "用户名包含特殊字符"),
PASSWORD_VERIFY_ERROR("A000120", "密码校验失败"),
PASSWORD_SHORT_ERROR("A000121", "密码长度不够"),
PHONE_VERIFY_ERROR("A000151", "手机格式校验失败"),
// ========== 二级宏观错误码 系统请求缺少幂等Token ==========
IDEMPOTENT_TOKEN_NULL_ERROR("A000200", "幂等Token为空"),
IDEMPOTENT_TOKEN_DELETE_ERROR("A000201", "幂等Token已被使用或失效"),
// ========== 一级宏观错误码 系统执行出错 ==========
SERVICE_ERROR("B000001", "系统执行出错"),
// ========== 二级宏观错误码 系统执行超时 ==========
SERVICE_TIMEOUT_ERROR("B000100", "系统执行超时"),
// ========== 一级宏观错误码 调用第三方服务出错 ==========
REMOTE_ERROR("C000001", "调用第三方服务出错");
private final String code;
private final String message;
BaseErrorCode(String code, String message) {
this.code = code;
this.message = message;
}
@Override
public String code() {
return code;
}
@Override
public String message() {
return message;
}
}
接下来,我们模拟用户恶意请求访问不存在的用户名,即缓存穿透的场景,看一下我们设计的异常码的真实应用。
首先分析,这种情况属于 B 类异常,B 类异常下又属于用户记录信息异常这一二级异常,由于系统在该级别下暂时没有其他的异常,该异常的异常码就可以定义为:B000200:
USER_NULL("B000200", "用户记录不存在")
测试结果:
{
"code":"B000200”,
"message'":“用户记录不存在”,
"data":null,
"requestId":null,
"success": false
}
进一步地,还可将与业务有关的异常码单独抽取成业务强关联的异常码枚举类:
Comments NOTHING