checked exception 和 unchecked exception

  • checked exception:编译器检查的异常,必须处理
  • unchecked exception:运行时异常,编译器不检查的异常

摒弃checked exception, 全部使用unchecked exception, 使用 RuntimeException 作为所有运行时异常的父类,

引擎使用 SnestException 作为所有异常的父类.

引擎异常使用

/**
 * 引擎异常基类,其他异常都需要继承此
 *
 * @author
 */
public class SnestException extends RuntimeException {

    private ErrorCode errorEnum = ErrorCode.UNKNOWN_EXC;
    private Integer errorCode;
    private String messageFormat;
    private Object[] args;

    /**
     * 返回国际化翻译过后的错误信息
     *
     * @return
     */
    @Override
    public String getMessage() {
        return this.messageFormat == null ||
                "".equals(this.messageFormat.trim()) ? super.getMessage() : MultiLangUtil.l10n(this.messageFormat, this.args);
    }

    /**
     * 获取多语言的错误信息(从上下文meta中获取当前语言)
     *
     * @return 多语言的错误信息
     */
    @Override
    public String getLocalizedMessage() {
        return MultiLangUtil.l10n(this.messageFormat, this.args);
    }
}
SnestException 类包含 ErrorCode 枚举,ErrorCode 枚举包含了所有的错误码和错误信息,使用时直接创建即可,SnestException 会自动格式化对应的错误信息。

如果自定义错误信息,SnestException 会自动格式化对应的错误信息。

也可以继承 SnestException 类,重写 getMessage() 方法,返回自定义的错误信息。

异常也可以继续传递给下一个异常,形成异常链。

public class AccessException extends SnestException {

    // 具体异常使用定义好的错误码
    protected static ErrorCode errorCode = ErrorCode.ACCESS_EXC;

    public AccessException() {
        super(errorCode);
    }

    public AccessException(Throwable cause) {
        super(errorCode, cause);
    }

    public AccessException(String message) {
        super(errorCode.getCode(), message);
    }

    public AccessException(String message, Throwable cause) {
        super(errorCode.getCode(), message, cause);
    }

    public AccessException(String messageFormat, Object... args) {
        super(errorCode.getCode(), messageFormat, args);
    }

    public AccessException(Throwable cause, String messageFormat, Object... args) {
        super(cause, errorCode.getCode(), null, messageFormat, args);
    }

}

public class EngineException extends SnestException {

    // 定义错误码
    protected static ErrorCode errorEnum = ErrorCode.ENGINE_EXC;

    public EngineException() {
        super(errorEnum);
    }

    public EngineException(Throwable cause) {
        super(errorEnum, cause);
    }

    public EngineException(String message) {
        super(errorEnum.getCode(), message);
    }

    public EngineException(String message, Throwable cause) {
        super(errorEnum.getCode(), message, cause);
    }

    public EngineException(String message, int errorCode) {
        super(errorCode, message);
    }

    public EngineException(int errorCode, String messageFormat, Object... args) {
        super(errorCode, messageFormat, args);
    }

    public EngineException(String messageFormat, Object... args) {
        super(errorEnum.getCode(), messageFormat, args);
    }

    public EngineException(Throwable cause, String messageFormat, Object... args) {
        super(cause, errorEnum.getCode(), null, messageFormat, args);
    }

}

错误码定义



/**
 * 错误码,统一在此处定义
 *
 * @author xiaomi
 */
public enum ErrorCode {

    /**
     * 错误日志对照表
     */
    ARGUMENT_NULL_EXC(100, "参数为空异常"),
    DATA_FORMAT_EXC(101, "数据格式异常"),
    VALUE_EXC(105, "值异常(值的范围、格式、类型不符合预期)"),
    DATA_EXC(200, "数据异常,数据持久化失败"),
    DB_EXC(201, "执行DB操作异常"),
    SQL_PARSE_EXC(205, "SQL解析异常"),
    MISSING_EXC(300, "缺失异常(找不到期望的参数、值、对象等)"),
    DATA_MISSING_EXC(335, "数据异常"),
    UNSUPPORTED_EXC(341, "暂不支持异常"),

    /** 擎相关  */
    ENGINE_EXC(400, "引擎内部异常"),
    UNAUTHORIZED_EXC(401, "未登录"),
    FORBIDDEN_EXC(403, "无权限访问"),
    APP_EXC(405, "APP异常"),
    META_EXC(500, "元模型异常"),
    MODEL_EXC(504, "模型异常"),
    SERVICE_ORCHESTRATE_EXC(505, "元模型异常,元模型定义不符合要求导致建构元模型失败"),
    CALL_EXC(600, "call调用服务(方法)异常"),
    PROXY_EXC(601, "动/静态代理执行异常"),
    REFLECT_EXC(602, "反射执行异常"),
    SIDE_CAR_EXC(630, "分布式sideCar异常"),
    UNKNOWN_EXC(999, "未知异常"),

    USER_EXC(1000, "用户异常"),
    VALIDATION_EXC(2000, "校验失败"),
    ACCESS_EXC(7000, "访问异常"),

    REDIS_MODEL_META(10000, "引擎Redis异常"),
    REDIS_FINAL_MODEL(10000, "引擎Redis异常,模型终态数据有误."),
    REDIS_PROPERTY_META(10001, "引擎Redis异常,属性初态数据有误."),
    REDIS_METHOD_META(10002, "引擎Redis异常,方法初态数据有误."),
    REDIS_SERVICE_META(10003, "引擎Redis异常,服务初态数据有误."),
    REDIS_PARAM_META(10004, "引擎Redis异常,服务参数初态数据有误."),

    SIDE_CAR_NOT_FOUND_APP(15000, "未找到应用: %s"),
    SIDE_CAR_INSTALLING_APP(15001, "正在安装应用: %s"),
    ENGINE_PLUGIN(20000, "引擎插件异常"),

    // SDK 相关
    SDK_EXC(21000, "SDK异常"),

    ;

    private static final Map<Integer, ErrorCode> ERROR_CODE_MAP = convertToErrorCodeMap();

    private int code;
    private String msg;

    ErrorCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public static Map<Integer, ErrorCode> getErrorCodeMap() {
        return ERROR_CODE_MAP;
    }

    private static Map<Integer, ErrorCode> convertToErrorCodeMap() {
        return Arrays.stream(ErrorCode.values()).collect(Collectors.toMap(e -> e.code, Function.identity(), (prev, next) -> next));
    }
}


/*
错误码规则:
               xx                     xx                                 xx
        两位代表具体的app    两位代表具体app中某个model         具体业务类型的具体的错误类型

举例:120200    
               12                      02                              00
            操作日志app              黑名单类型                   黑名单参数异常
*/

// 公共错误码 10
const (
    ErrUnknown             = -1
    ErrOk                  = 0
    ErrParameterInvalid    = 100001
    ErrInternalServerError = 100002
    ErrRequestTimeout      = 100003
    ErrCallServiceTimeout  = 100004
)

var errTextMap = map[int]string{
    ErrUnknown:             "未知错误",
    ErrOk:                  "成功",
    ErrParameterInvalid:    "请求参数错误",
    ErrInternalServerError: "服务内部错误",
    ErrRequestTimeout:      "请求超时,请稍后重试",
    ErrCallServiceTimeout:  "调用服务超时",
}