让错误码规范起来吧
一、前言
1、不规范的错误码有什么问题?
1)理解困难
描述:如果错误码的命名或描述不清晰,可能导致其他开发人员难以理解其含义。
举例:例如,一个错误码命名为“ERR1001”,没有进一步的注释或描述,可能导致其他开发人员不知道这个错误码代表的具体问题。
2)不一致性
描述: 如果错误码的命名、描述或分类不统一,可能导致代码的可读性和可维护性降低。
举例:例如,有的错误码使用三位数,有的使用两位数;有的错误码描述具体的问题,而有的描述则较为模糊。
3)排查困难
描述:如果错误码没有清晰的命名和描述,可能使得调试过程变得困难。
举例:当出现问题时,开发人员需要查看大量的日志或代码来定位问题所在。
4)冗余和重复
描述:如果错误码过多或过于复杂,可能导致代码中的错误处理逻辑变得冗余和重复。
举例:同一个错误可能在不同地方有不同的错误码,导致处理逻辑重复。
5)扩展性差
描述:如果错误码已经定义但后来需要添加新的错误码,可能需要修改多个地方的代码,增加了维护成本。
2、规范的错误码那么好,为什么不规范使用呢?
1)缺乏规范和标准:
在某些情况下,可能没有明确的规范或标准来指导如何使用错误码。这可能导致开发人员根据自己的理解和习惯来定义错误码,从而导致不规范的情况。
2)缺乏意识和经验:
某些开发人员可能没有意识到错误码规范化的重要性,或者缺乏足够的经验来正确地设计和使用错误码。
3)历史遗留问题:
在某些项目中,错误码可能已经使用了很长时间,而且已经成为了代码的一部分。在这种情况下,重新规范化错误码可能会涉及到大量的代码修改和测试,这可能会被视为成本较高。
4)个人习惯和偏好:
某些开发人员可能更倾向于按照自己的习惯和偏好来使用错误码,而不是遵循团队的规范。这可能会导致代码中的错误码使用不一致。
3、那怎么规范错误码呢
1)制定规范和标准:
团队可以制定明确的规范和标准,指导如何使用错误码,并将其纳入代码审查和开发流程中。
2)培训和指导:
为新开发人员提供培训和指导,使其了解如何正确地设计和使用错误码。
3)重构和改进:
对于历史遗留问题,可以通过逐步重构和改进的方式来规范化错误码的使用。
4)代码审查和团队协同:
通过代码审查和团队协同来确保错误码的规范化和一致性。
二、规范错误码
1、错误码-分片区
根据号段区分错误类型,这里长度定义了5位,可以根据自己系统规模调整长度
错误码 | 描述 |
---|---|
00000 | 成功 |
10000 | 参数错误 |
20000 | 业务处理失败(业务上给用户吐出) |
30000 | RPC处理失败 --->> 系统_失败分类(请求0、返回1)_业务_方法_调用方CODE码(代码补齐),极端情况下吐出 99999 |
40000 | 运行处理失败:一般内部处理使用,极端情况下吐出 99999 |
99999 | 系统太火爆了,请稍后重试! -->极端情况下才吐出 |
@Getter
@AllArgsConstructor
enum ErrorCodeEnum implements CodeEnum {
ERROR_CODE_SUCCESS("00000", "成功"),
ERROR_CODE_PARAMS_ERROR("10000", "参数错误"),
ERROR_CODE_BUSINESS_ERROR("20000", "业务处理失败"),
ERROR_CODE_PRC_ERROR("30000", "RPC处理失败"),
ERROR_CODE_RUNTIME_ERROR("40000", "运行时失败"),
ERROR_CODE_FAIL("99999", "系统太火爆了,请稍后重试!"),
;
private final String code;
private final String msg;
}
2、10000-参数异常
非常简单,直接吐出即可
参数 | 说明 |
---|---|
code |
错误码 |
msg |
返回错误信息 |
@Getter
@AllArgsConstructor
enum ParamsErrorEnum implements CodeEnum {
ERROR_CODE_10000("10000", "参数错误"),
ERROR_CODE_10001("10001", "不支持的请求方式"),
ERROR_CODE_10002("10002", "参数格式异常"),
;
private final String code;
private final String msg;
}
3、20000-业务异常
参数 | 说明 |
---|---|
code |
错误码 |
msg |
底层-错误信息 |
showMsg |
吐出-错误信息 |
@Getter
@AllArgsConstructor
enum BusinessErrorEnum implements CodeEnum {
ERROR_CODE_20000("20000", "业务处理失败", "系统太火爆了,请稍后重试!"),
ERROR_CODE_20001("20001", "订单创建失败", "您有一个订单正在创建,请稍后查看"),
ERROR_CODE_20002("20002", "付款失败,存在创建中的订单", "您的订单付款失败,请稍后查看"),
ERROR_CODE_20003("20003", "付款失败,存在未支付的订单", "您的订单付款失败,请稍后查看"),
;
private final String code;
private final String msg;
private final String showMsg;
}
4、30000-RPC
异常
该异常一定要合理使用,这样会让微服务直接错误信息更明确
说明:
系统_失败分类(请求0、返回1)_业务_调用方法_调用方CODE码(代码补齐)
字段 | 说明 |
---|---|
系统 | 调用系统:如用户系统 User |
失败分类 | 请求失败:0;返回失败:1 |
业务 | 业务(3开头):用户信息业务:30001 |
调用方法 | 业务调用方法(指定一个数字,确保是该业务唯一的方法) |
调用方Code 码 |
后续代码中补齐,具体看异常抛出错误码使用 |
参数 | 说明 |
---|---|
code |
错误码:系统_失败分类(请求0、返回1)_业务_方法_调用方CODE码(代码补齐) |
msg |
底层-错误信息 |
@Getter
@AllArgsConstructor
enum RpcErrorEnum implements CodeEnum {
/**
* 系统_失败分类(请求0、返回1)_业务_方法_调用方CODE码(代码补齐)
*/
ERROR_CODE_USER_0_30001_0001("USER_0_30001_0001", "RPC异常-USER-用户信息-查询单个用户信息-接口调用失败"),
ERROR_CODE_USER_1_30001_0001("USER_1_30001_0001", "RPC异常-USER-用户信息-查询单个用户信息-接口返回失败"),
ERROR_CODE_USER_1_30001_0002("USER_1_30001_0002", "RPC异常-USER-用户信息-分页查询用户信息-接口返回失败"),
;
private final String code;
private final String msg;
}
5、40000-运行异常
@Getter
@AllArgsConstructor
enum PlatformErrorEnum implements CodeEnum {
ERROR_CODE_40000("40000", "运行时失败"),
ERROR_CODE_40001("40001", "路由消息处理失败"),
;
private final String code;
private final String msg;
}
三、错误码使用
1、10000-参数异常
构造器 | 说明 |
---|---|
ParameterException(CodeEnum.ParamsErrorEnum paramErrorEnum) |
建议使用:传入一个固定的枚举值 |
ParameterException(String message) |
不推荐:传入一个错误信息 |
@Getter
public class ParameterException extends RuntimeException {
/**
* serialVersionUID
*/
private static final long serialVersionUID = -6114625076221233075L;
/**
* 返回错误码
*/
private final String code;
/**
* BusinessException
*
* @param paramErrorEnum paramErrorEnum
*/
public ParameterException(CodeEnum.ParamsErrorEnum paramErrorEnum) {
super(paramErrorEnum.getMsg());
this.code = paramErrorEnum.getCode();
}
/**
* ParameterErrorException
*
* @param message message
*/
public ParameterException(String message) {
super(message);
this.code = CodeEnum.ErrorCodeEnum.ERROR_CODE_PARAMS_ERROR.getCode();
}
}
2、20000-业务异常
构造器 | 说明 |
---|---|
BusinessException(CodeEnum.BusinessErrorEnum businessErrorEnum) |
建议使用:传入一个固定的枚举值 |
BusinessException(String message) |
不推荐:传入一个错误信息 |
@Getter
public class BusinessException extends RuntimeException {
/**
* serialVersionUID
*/
private static final long serialVersionUID = 799633539625676004L;
/**
* 返回错误码
*/
private final String code;
/**
* 展示信息
*/
private final String showMsg;
/**
* BusinessException
*
* @param businessErrorEnum businessErrorEnum
*/
public BusinessException(CodeEnum.BusinessErrorEnum businessErrorEnum) {
super(businessErrorEnum.getMsg());
this.code = businessErrorEnum.getCode();
this.showMsg = businessErrorEnum.getShowMsg();
}
/**
* BusinessException
*
* @param message message
*/
public BusinessException(String message) {
super(message);
this.code = CodeEnum.ErrorCodeEnum.ERROR_CODE_BUSINESS_ERROR.getCode();
this.showMsg = message;
}
}
3、30000-RPC
异常
构造器 | 说明 |
---|---|
RpcException(CodeEnum.RpcErrorEnum rpcErrorEnum) |
场景:处理未知的RPC 异常,如网络超时等 |
RpcException(CodeEnum.RpcErrorEnum rpcErrorEnum, String code, String showMsg) |
场景:处理已知的异常 |
RpcException(CodeEnum.RpcErrorEnum rpcErrorEnum, String code, String msg, String showMsg) |
场景:处理已知的异常 |
@Getter
public class RpcException extends RuntimeException {
/**
* serialVersionUID
*/
private static final long serialVersionUID = 799633539625676004L;
/**
* 返回错误码
*/
private final String code;
/**
* 展示信息
*/
private final String showMsg;
/**
* RpcException-处理未知的异常
*
*
* @param rpcErrorEnum rpcErrorEnum
*/
public RpcException(CodeEnum.RpcErrorEnum rpcErrorEnum) {
super(rpcErrorEnum.getMsg());
this.code = rpcErrorEnum.getCode();
this.showMsg = CodeEnum.ErrorCodeEnum.ERROR_CODE_FAIL.getMsg();
}
/**
* RpcException 处理已知的异常
*
* @param rpcErrorEnum rpcErrorEnum
* @param code code
* @param showMsg showMsg
*/
public RpcException(CodeEnum.RpcErrorEnum rpcErrorEnum, String code, String showMsg) {
super(rpcErrorEnum.getMsg());
this.code = rpcErrorEnum.getCode() + "_" + code;
this.showMsg = showMsg;
}
/**
* RpcException 处理已知的异常
*
* @param rpcErrorEnum rpcErrorEnum
* @param code code
* @param showMsg showMsg
*/
public RpcException(CodeEnum.RpcErrorEnum rpcErrorEnum, String code, String msg, String showMsg) {
super(msg);
this.code = rpcErrorEnum.getCode() + "_" + code;
this.showMsg = showMsg;
}
}
4、40000-运行异常
@Getter
public class PlatformException extends RuntimeException {
private static final long serialVersionUID = 5535821215702463243L;
/**
* 返回错误码
*/
private final String code;
/**
* 展示信息
*/
private final String showMsg;
/**
* PlatformException
*
* @param platformErrorEnum platformErrorEnum
*/
public PlatformException(CodeEnum.PlatformErrorEnum platformErrorEnum) {
super(platformErrorEnum.getMsg());
this.code = platformErrorEnum.getCode();
this.showMsg = CodeEnum.ErrorCodeEnum.ERROR_CODE_FAIL.getMsg();
}
}
四、异常吐出
1、10000-参数异常
/**
* 不支持的请求方始
*/
@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
@ResponseStatus(value = HttpStatus.METHOD_NOT_ALLOWED)
public BaseRes<?> methodNotSupportExceptionHandler(HttpRequestMethodNotSupportedException e) {
log.error("不支持的请求方式", e);
return BaseRes.buildFailure(CodeEnum.ParamsErrorEnum.ERROR_CODE_10001.getCode(), e.getMessage());
}
/**
* 参数类型错误
*/
@ExceptionHandler(value = {BindException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public BaseRes<?> bindExceptionHandler(BindException e) {
log.error("====参数类型错误===", e);
return BaseRes.buildFailure(CodeEnum.ParamsErrorEnum.ERROR_CODE_10000);
}
/**
* 参数格式问题
*/
@ExceptionHandler(value = {MethodArgumentTypeMismatchException.class,
HttpMessageConversionException.class, UnexpectedTypeException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public BaseRes<?> httpMessageConversionExceptionHandler(Exception e) {
log.error("====参数格式异常===", e);
return BaseRes.buildFailure(CodeEnum.ParamsErrorEnum.ERROR_CODE_10002);
}
/**
* 参数错误
*/
@ExceptionHandler(value = ParameterException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public BaseRes<?> parameterErrorExceptionHandler(ParameterException e) {
log.error("====参数异常:code:{},msg:{}", e.getCode(), e.getMessage(), e);
return BaseRes.buildFailure(e.getCode(), e.getMessage());
}
2、20000-业务异常
/**
* 业务异常,给前台返回异常数据
*/
@ExceptionHandler(value = BusinessException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public BaseRes<?> businessExceptionHandler(BusinessException e) {
log.error("====业务异常:code:{},msg:{},showMsg:{}", e.getCode(), e.getMessage(), e.getShowMsg(), e);
return BaseRes.buildFailure(e.getCode(), e.getShowMsg());
}
3、30000-RPC
异常
/**
* RPC,给前台返回异常数据
*/
@ExceptionHandler(value = RpcException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public BaseRes<?> rpcExceptionHandler(RpcException e) {
log.error("====RPC异常:code:{},msg:{},showMsg:{}", e.getCode(), e.getMessage(), e.getShowMsg(), e);
return BaseRes.buildFailure(e.getCode(), e.getShowMsg());
}
4、40000-运行异常
/**
* 运行异常,给前台返回异常数据
*/
@ExceptionHandler(value = PlatformException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public BaseRes<?> rpcExceptionHandler(PlatformException e) {
log.error("====运行异常:code:{},msg:{},showMsg:{}", e.getCode(), e.getMessage(), e.getShowMsg(), e);
return BaseRes.buildFailure(e.getCode(), e.getShowMsg());
}
五、Demo
1、10000-参数异常
@ApiOperation("parameterExceptionEnum")
@LogIndex
@GetMapping("parameterExceptionEnum")
@ResponseBody
public BaseRes<List<UserDemoVO>> parameterExceptionEnum() {
throw new ParameterException(CodeEnum.ParamsErrorEnum.ERROR_CODE_10002);
}
{
"success": false,
"data": null,
"msg": "参数格式异常",
"code": "10002"
}
@ApiOperation("parameterExceptionMsg")
@LogIndex
@GetMapping("parameterExceptionMsg")
@ResponseBody
public BaseRes<List<UserDemoVO>> parameterExceptionMsg() {
throw new ParameterException("用户Id不能为空");
}
{
"success": false,
"data": null,
"msg": "用户Id不能为空",
"code": "10000"
}
2、20000-业务异常
@ApiOperation("businessExceptionEnum")
@LogIndex
@GetMapping("businessExceptionEnum")
@ResponseBody
public BaseRes<List<UserDemoVO>> businessExceptionEnum() {
throw new BusinessException(CodeEnum.BusinessErrorEnum.ERROR_CODE_20001);
}
{
"success": false,
"data": null,
"msg": "您有一个订单正在创建,请稍后查看",
"code": "20001"
}
@ApiOperation("businessExceptionMsg")
@LogIndex
@GetMapping("businessExceptionMsg")
@ResponseBody
public BaseRes<List<UserDemoVO>> businessExceptionMsg() {
throw new BusinessException("用户创建失败");
}
{
"success": false,
"data": null,
"msg": "用户创建失败",
"code": "20000"
}
3、30000-RPC
异常
@ApiOperation("rpcExceptionDefaultEnum")
@LogIndex
@GetMapping("rpcExceptionDefaultEnum")
@ResponseBody
public BaseRes<List<UserDemoVO>> rpcExceptionDefaultEnum() {
throw new RpcException(CodeEnum.RpcErrorEnum.ERROR_CODE_USER_0_30001_0001);
}
{
"success": false,
"data": null,
"msg": "系统太火爆了,请稍后重试!",
"code": "USER_0_30001_0001"
}
@ApiOperation("rpcExceptionEnumShowMsg")
@LogIndex
@GetMapping("rpcExceptionEnumShowMsg")
@ResponseBody
public BaseRes<List<UserDemoVO>> rpcExceptionEnumShowMsg() {
throw new RpcException(CodeEnum.RpcErrorEnum.ERROR_CODE_USER_1_30001_0001, "1000", "用户不存在");
}
{
"success": false,
"data": null,
"msg": "用户不存在",
"code": "USER_1_30001_0001_1000"
}
@ApiOperation("rpcExceptionEnumMsg")
@LogIndex
@GetMapping("rpcExceptionEnumMsg")
@ResponseBody
public BaseRes<List<UserDemoVO>> rpcExceptionEnumMsg() {
throw new RpcException(CodeEnum.RpcErrorEnum.ERROR_CODE_USER_1_30001_0001,
"1000", "底层结构异常", "用户不存在");
}
{
"success": false,
"data": null,
"msg": "用户不存在",
"code": "USER_1_30001_0001_1000"
}
4、40000-运行异常
@ApiOperation("platformException")
@LogIndex
@GetMapping("platformException")
@ResponseBody
public BaseRes<List<UserDemoVO>> platformException() {
throw new PlatformException(CodeEnum.PlatformErrorEnum.ERROR_CODE_40001);
}
{
"success": false,
"data": null,
"msg": "系统太火爆了,请稍后重试!",
"code": "40001"
}
作者:京东保险 张宇晋
来源:京东云开发者社区 转载请注明来源

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
GaussDB元命令使用指导
所谓元命令就是在gsql里输入的任何以不带引号的反斜杠开头的命令。本课程通过实际使用gsql实践,介绍GaussDB数据库gsql所提供的元命令。 本课程仅展示基础的元命令使用。 一、操作步骤 步骤1 使用gsql连接到GaussDB实例。 gsql工具使用-d参数指定目标数据库名、-U参数指定数据库用户名、-h参数指定主机名、-p参数指定端口号信息。 若未指定数据库名称,则使用初始化时默认生成的数据库名称;若未指定数据库用户名,则默认使用当前操作系统用户作为数据库用户名;当某个值没有前面的参数(-d、-U等)时,若连接的命令中没有指定数据库名(-d)则该参数会被解释成数据库名;如果已经指定数据库名(-d)而没有指定数据库用户名(-U)时,该参数则会被解释成数据库用户名。 示例,使用root用户连接到远程主机postgres数据库的8000端口。 gsql -h 10.180.123.163 -d postgres -U root -p 8000复制 步骤2 使用元命令查看所有的数据库。 l 回显如下: Name | Owner | Encoding | Collate | Ctype...
-
下一篇
京东广告算法架构体系建设--在线模型系统分布式异构计算演变 | 京东零售广告技术团队
一、现状介绍 算法策略在广告行业中起着重要的作用,它可以帮助广告主和广告平台更好地理解用户行为和兴趣,从而优化广告投放策略,提高广告点击率和转化率。模型系统作为承载算法策略的载体,目前承载搜索、推荐、首焦、站外等众多广告业务和全链路的深度学习建模,是广告算法算法创新和业务迭代发展的重要基石。 架构全景图: 1. 平台能力: 1. 高吞吐高并发:百亿PV,百万QPS 2. 低延迟,高可靠:万亿次预估计算/秒,毫秒级延迟,99.99% 3. 集群规模:1W+节点 4. 迭代周期:3次/天 2. 系统能力 1. 模型规模:TB级模型预估 2. 异构计算:CPU/GPU异构计算 3. 在线学习:分钟级模型更新 4. 实时图计算:亿级节点、百亿级边;分钟级图数据更新 5. 层次化算力:实时计算、离线计算、近线计算 二、发展历程 广告在线模型系统发展大致分为三个主要阶段: 1、深度学习时代:通过组件化、平台化、配置化完成架构的统一和流程机制的规范化,解决迭代效率问题。 2、大模型时代:通过分布式分图计算架构解决模型规模和实效性的问题。 3、算力时代:通过层次化算力建设解决...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- MySQL8.0.19开启GTID主从同步CentOS8
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Dcoker安装(在线仓库),最新的服务器搭配容器使用
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- MySQL数据库在高并发下的优化方案
- Docker容器配置,解决镜像无法拉取问题