Spring Boot自定义异常

jasmine 于 2020-05-01 发布

1、定义ErrorCode接口

public interface ErrorCode {
    ErrorCode SUCCESS = new Default("000", "ok");

    String getCode();

    String getMsg();

    
    default boolean is(String code) {
        return this.getCode().equals(code);
    }

    default boolean is(ErrorCode error) {
        return error != null && this.is(error.getCode());
    }

    static boolean isSuccess(String code) {
        return SUCCESS.is(code);
    }

    class Default implements ErrorCode {
        private final String code;
        private final String msg;

        public String getCode() {
            return this.code;
        }

        public String getMsg() {
            return this.msg;
        }

        public Default(final String code, final String msg) {
            this.code = code;
            this.msg = msg;
        }
    }
}

2、定义code码ErrCodeEnum

public enum ErrCodeEnum implements ErrorCode {

    UNSPECIFIED("500", "服务繁忙,请稍后再试"),
    USER_NOT_LOGIN("2120208001", "用户未登录"),

    ;

    private final String code;
    private final String msg;

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

    /**
     * 根据编码查询枚举。
     *
     * @param code 编码。
     * @return 枚举。
     */
    public static ErrCodeEnum getByCode(String code) {
        for (ErrCodeEnum value : ErrCodeEnum.values()) {
            if (value.getCode().equals(code)) {
                return value;
            }
        }
        return UNSPECIFIED;
    }

    /**
     * 枚举是否包含此code
     *
     * @param code 枚举code
     * @return 结果
     */
    public static Boolean contains(String code) {
        for (ErrCodeEnum value : ErrCodeEnum.values()) {
            if (value.getCode().equals(code)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String getCode() {
        return code;
    }

    @Override
    public String getMsg() {
        return msg;
    }
}

3、自定义异常类PlatformException


/**
 * 自定义异常类
 */
public class PlatformException extends Exception {

    protected final ErrorCode errorCode;


    public PlatformException(final ErrorCode errorCode) {
        super(errorCode.getMsg());
        this.errorCode = errorCode;
    }

    public PlatformException(final String msg) {
        super(msg);
        this.errorCode = ErrCodeEnum.UNSPECIFIED;
    }

    public PlatformException(final ErrorCode errorCode, final Throwable t) {
        super(errorCode.getMsg(), t);
        this.errorCode = errorCode;
    }

    public ErrorCode getErrorCode() {
        return errorCode;
    }

}

4、异常拦截器ControllerAdviceProcessor

@ControllerAdvice
@Slf4j
public class ControllerAdviceProcessor {

    @Autowired
    protected MessageSource messageSource;

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Response<?> handleException(HttpServletRequest request, Exception ex) {

        String code = "500";
        if (ex instanceof HttpMessageNotReadableException) {
            code = "400";
        } else if (ex instanceof HttpRequestMethodNotSupportedException) {
            code = "999";
        }
        String msg = null;


        if (ex instanceof PlatformException) {
            PlatformException PlatformException = (PlatformException) ex;
            msg = PlatformException.getMessage();
            code = PlatformException.getErrorCode().getCode();

        } else if (ex instanceof AccessDeniedException) {
            msg = "无权限访问";
            code = "403";
        }
        if (msg == null) {
            msg = ex.getMessage();
        }
        log.error("---【err】---ControllerAdviceProcessor---code: " + code + "  msg: " + msg, ex);
        return Response.error(code, msg);
    }
}

5、定义返回工具类Response

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

@Getter
@Setter
@ToString
@Accessors(chain = true)
public class Response<T> {

    // 错误码
    private String code = "000";

    // 错误信息文本
    private String msg = "ok";

    // 消息主体
    private T data;

    protected Response() {
    }

    /**
     * 快速构建异常返回对象
     *
     * @param code 错误码
     * @param msg  错误信息
     * @param <T>  主体类型
     * @return 响应体
     */
    public static <T> Response<T> error(String code, String msg) {
        return new Response<T>()
                .setCode(code)
                .setMsg(msg);
    }

    /**
     * 快速构建异常返回对象
     *
     * @param error 错误码枚举
     * @param <T>   主体类型
     * @return 响应体
     */
    public static <T> Response<T> error(ErrorCode error) {
        return error(error.getCode(), error.getMsg());
    }

    /**
     * 快速构建成功返回对象
     *
     * @param <T> 主体类型
     * @return 响应体
     */
    public static <T> Response<T> success() {
        return new Response<>();
    }

    /**
     * 快速构建带消息主体的成功返回对象
     *
     * @param data 消息主体
     * @param <T>  主体类型
     * @return 响应体
     */
    public static <T> Response<T> success(T data) {
        return Response.<T>success().setData(data);
    }

}

6、code码定义规范

规则如下:
【xx】 - 【xxx】 - 【xxxxx】
业务组 子模块 异常码

业务码规范