laitimes

Let's normalize the error code

author:JD Cloud developer

I. Preface

1. What is the problem with non-standard error codes?

1) Difficulty in understanding

Description: If the error code is not clearly named or described, it can make it difficult for other developers to understand what it means.

For example, if an error code is named "ERR1001" without further comments or descriptions, other developers may not know what the error code represents.

2) Inconsistencies

Description: If the naming, description, or classification of error codes is not uniform, it may lead to reduced readability and maintainability of the code.

For example, some error codes use three digits and some use two digits, while others describe specific problems and some are vague.

3) Difficulty in troubleshooting

Description: If the error code is not clearly named and described, it can make the debugging process difficult.

Example: When something goes wrong, developers need to look at a lot of logs or code to locate the problem.

4) Redundancy and duplication

Description: If there are too many or too complex error codes, the error handling logic in the code may become redundant and repetitive.

For example, the same error may have different error codes in different places, resulting in duplicate processing logic.

5) Poor scalability

Description: If an error code has already been defined but a new error code needs to be added later, you may need to modify the code in multiple places, which increases maintenance costs.

2. The standardized error code is so good, why not standardize the use?

1) Lack of norms and standards:

In some cases, there may not be clear specifications or standards to guide how to use error codes. This can lead to developers defining error codes based on their own understanding and habits, leading to irregularities.

2) Lack of awareness and experience:

Some developers may not realize the importance of error code normalization or lack sufficient experience to properly design and use error codes.

3) Historical Legacy Issues:

In some projects, error codes may have been used for a long time and have become part of the code. In this case, renormalizing error codes can involve a lot of code modification and testing, which may be seen as costly.

4) Personal Habits and Preferences:

Some developers may prefer to use error codes according to their own habits and preferences rather than following the team's specifications. This can lead to inconsistent usage of error codes in the code.

3. How to standardize the error code

1) Development of norms and standards:

Teams can develop clear specifications and standards for how to use error codes and incorporate them into the code review and development process.

2) Training and Mentoring:

Provide training and guidance to new developers on how to properly design and use error codes.

3) Refactoring and Improvement:

For historical problems, the use of error codes can be normalized through gradual reconstruction and improvement.

4) Code Review and Team Collaboration:

Code reviews and team collaboration ensure normalization and consistency of error codes.

Second, standardize the error code

1. Error code - sharding

Error types are distinguished according to the number segment, and the length here is defined by 5 bits, which can be adjusted according to the size of your system
Error codes description
00000 success
10000 The parameter is incorrect
20000 Service Processing Failure (Vomiting to Users)
30000 RPC processing failed --->> System_Failure classification (request 0, return 1)_business_method_caller CODE (code completion), and in extreme cases, 99999 is spit out
40000 Run processing failed: Generally used for internal processing, in extreme cases 99999 is spit out
99999 The system is so hot, please try again later! --Spit > extreme cases
@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-parameter abnormal

It's very simple, just spit it out
parameter illustrate
code Error codes
msg An error message is returned
@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 - Business exception

parameter illustrate
code Error codes
msg Bottom - Error message
showMsg Spit out - error message
@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异常

This exception must be used wisely, as it will make the microservice's direct error message clearer

DESCRIPTION: SYSTEM_FAILURE CLASSIFICATION (REQUEST 0, RETURN 1)_BUSINESS_CALLING METHOD_CODE (code completion)

field illustrate
system Invoking the system: For example, the user system User
Failure classification Request failed: 0, Return failed: 1
business Business (starting with 3): User information business: 30001
Call the method Business invocation method (specify a number to ensure that it is the only method for that business)
The caller code Fill in the follow-up code, see the use of error codes thrown by exceptions
parameter illustrate
code Error Code: System_Failure Classification (Request 0, Return 1)_Business_Method_Caller CODE (Code Completion)
msg Bottom - Error message
@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 - abnormal operation

@Getter
@AllArgsConstructor
enum PlatformErrorEnum implements CodeEnum {

    ERROR_CODE_40000("40000", "运行时失败"),
    ERROR_CODE_40001("40001", "路由消息处理失败"),

    ;
    private final String code;

    private final String msg;

}

           

3. Use of error codes

1. 10000-parameter abnormal

Constructor illustrate
ParameterException(CodeEnum.ParamsErrorEnum paramErrorEnum) Recommended: Pass in a fixed enumerated value
ParameterException(String message) Not recommended: An error message is passed
@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 - Business abnormality

Constructor illustrate
BusinessException(CodeEnum.BusinessErrorEnum businessErrorEnum) Recommended: Pass in a fixed enumerated value
BusinessException(String message) Not recommended: An error message is passed
@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异常

Constructor illustrate
RpcException(CodeEnum.RpcErrorEnum rpcErrorEnum) Scenario: Handle unknown RPC exceptions, such as network timeouts
RpcException(CodeEnum.RpcErrorEnum rpcErrorEnum, String code, String showMsg) Scenario: Handle known exceptions
RpcException(CodeEnum.RpcErrorEnum rpcErrorEnum, String code, String msg, String showMsg) Scenario: Handle known exceptions
@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 - abnormal operation

@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();

    }
}
           

Fourth, abnormal spitting

1. 10000-parameter abnormal

/**
 * 不支持的请求方始
 */
@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 - Business abnormality

/**
 * 业务异常,给前台返回异常数据
 */
@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 - abnormal operation

/**
 * 运行异常,给前台返回异常数据
 */
@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-parameter abnormal

@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 - Business abnormality

@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 - abnormal operation

@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"
}
           

Author: JD Insurance Zhang Yujin

Source: JD Cloud Developer Community Please indicate the source for reprinting