让错误码规范起来吧

一、前言

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 系统太火爆了,请稍后重试! -->极端情况下才吐出
less 复制代码
@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 返回错误信息
less 复制代码
  @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 吐出-错误信息
less 复制代码
@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 底层-错误信息
less 复制代码
@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-运行异常

less 复制代码
@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) 不推荐:传入一个错误信息
scala 复制代码
@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) 不推荐:传入一个错误信息
scala 复制代码
@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) 场景:处理已知的异常
arduino 复制代码
@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-运行异常

scala 复制代码
@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-参数异常

kotlin 复制代码
/**
 * 不支持的请求方始
 */
@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-业务异常

less 复制代码
/**
 * 业务异常,给前台返回异常数据
 */
@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异常

less 复制代码
/**
 * 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-运行异常

less 复制代码
/**
 * 运行异常,给前台返回异常数据
 */
@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-参数异常

less 复制代码
@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"
}
less 复制代码
@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-业务异常

less 复制代码
@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"
}
less 复制代码
@ApiOperation("businessExceptionMsg")
@LogIndex
@GetMapping("businessExceptionMsg")
@ResponseBody
public BaseRes<List<UserDemoVO>> businessExceptionMsg() {
    throw new BusinessException("用户创建失败");
}

{
    "success": false,
    "data": null,
    "msg": "用户创建失败",
    "code": "20000"
}

3、30000-RPC异常

less 复制代码
    @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"
}
less 复制代码
@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"
}
less 复制代码
@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-运行异常

less 复制代码
@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"
}

作者:京东保险 张宇晋

来源:京东云开发者社区 转载请注明来源

相关推荐
Chenyiax1 分钟前
从一次请求看懂 OkHttp:架构、调度与连接管理
后端
爱勇宝1 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
AskHarries1 小时前
工具失败时怎么办:重试、回滚、人工确认和风险提示
后端·程序员
苏三说技术3 小时前
Claude Code从失控到起飞,只用了这些技巧
后端
长栎4 小时前
写 for 循环写了十年,你却从没用过迭代器模式最狠的那一面
后端
LiaCode4 小时前
Redis 在生产项目的使用
前端·后端
用户559822481224 小时前
Docker Compose Down 导致容器数据误删——ext4 日志恢复全记录
后端
LiaCode4 小时前
一天学完 redis 的爽翻版核心知识总结
前端·后端
大刚测试开发实战4 小时前
如何内网穿透访问本地私有化部署的TestHub
前端·后端·github
xiaodaoluanzha4 小时前
迄今為止,最簡單的編程語言 Nolang
前端·后端