您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
让错误码规范起来吧
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
让错误码规范起来吧
jd****
2024-01-17
IP归属:北京
173浏览
# 一、前言 ## 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 | **系统太火爆了,请稍后重试! -->极端情况下才吐出** | ```java @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` | 返回错误信息 | ```java @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` | 吐出-错误信息 | ```java @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` | 底层-错误信息 | ```java @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-运行异常 ```java @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) ` | 不推荐:传入一个错误信息 | ```java @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)` | 不推荐:传入一个错误信息 | ```java @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)` | 场景:处理已知的异常 | ```java @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-运行异常 ```java @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-参数异常 ```java /** * 不支持的请求方始 */ @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-业务异常 ```java /** * 业务异常,给前台返回异常数据 */ @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`异常 ```java /** * 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-运行异常 ```java /** * 运行异常,给前台返回异常数据 */ @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-参数异常 ```java @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" } ``` ```java @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-业务异常 ```java @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" } ``` ```java @ApiOperation("businessExceptionMsg") @LogIndex @GetMapping("businessExceptionMsg") @ResponseBody public BaseRes<List<UserDemoVO>> businessExceptionMsg() { throw new BusinessException("用户创建失败"); } { "success": false, "data": null, "msg": "用户创建失败", "code": "20000" } ``` ## 3、30000-`RPC`异常 ```java @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" } ``` ```java @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" } ``` ```java @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-运行异常 ```java @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" } ```
上一篇:《Hive编程指南》读书笔记
下一篇:京东广告算法架构体系建设--在线模型系统分布式异构计算演变 | 京东零售广告技术团队
jd****
文章数
1
阅读量
73
作者其他文章
01
让错误码规范起来吧
一、前言1、不规范的错误码有什么问题?1)理解困难描述:如果错误码的命名或描述不清晰,可能导致其他开发人员难以理解其含义。举例:例如,一个错误码命名为“ERR1001”,没有进一步的注释或描述,可能导致其他开发人员不知道这个错误码代表的具体问题。2)不一致性描述: 如果错误码的命名、描述或分类不统一,可能导致代码的可读性和可维护性降低。举例:例如,有的错误码使用三位数,有的使用两位数;有的错误码描
jd****
文章数
1
阅读量
73
作者其他文章
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号