动手写个java快速开发框架-(4)统一异常处理

作为一个开发框架当然稍不了异常的统一处理,今天我们就在MkFramework中加入统一异常处理模块。大家在日常开发过程中,对于一些初级开发经常喜欢将代码框在try代码块中,然后在catch中进行异常捕获,但很多都只是在捕获了之后只是进行简单的print错误堆栈信息,这样就会导致系统报错了,但是我们在日志中看不到抛出的异常信息,或者是有些自认为可以进行处理的错误,其实没有处理成功,所以很多框架都加入了统一异常处理机制,这样就可以让所有的错误处理集中在一个地方进行处理,在业务代码开发过程中,遇到错误只需要进行throw就可以了,由上层统一进行拦截处理,返回给调用方。

对于一个框架中,当然也要有错误码的统一管理,这里我们使用了自定义错误码,并将错误码定义在了错误码枚举类中,当然如果你的系统比较庞大,错误码非常多,并且要实现错误码的动态调整,那么也可以将错误码存在数据库中,启动后放到内存缓存,这里为了方便大家理解只是提前将错误码定义在了枚举类中。

所有的错误码定义和错误异常处理都放在了common.exception包中。

我们定义的错误类为MkException,对于我们业务中的错误都可以使用自定义异常类,对于java runtime异常或者Error还是建议不做过多的封装,这样便于查询问题。

public class MkException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    
    private String returnMsg;
    /**
     * returnCode 表示HOP内部错误码
     */
    private String returnCode = "999999";
    private String errorMsg;

    /**
     * errorCode 表示后台系统返回错误码
     */
    private String errorCode = "999999";
    //...省略N个重载的构造函数
    public MkException(String returnMsg, String returnCode, String errorMsg, String errorCode) {
        super(returnMsg);
        this.returnMsg = returnMsg;
        this.returnCode = returnCode;
        this.errorMsg = errorMsg;
        this.errorCode = errorCode;
    }

    public MkException(String returnMsg, String returnCode, String errorMsg, String errorCode, Throwable e) {
        super(returnMsg, e);
        this.returnMsg = returnMsg;
        this.returnCode = returnCode;
        this.errorMsg = errorMsg;
        this.errorCode = errorCode;
    }

    public MkException(ResultCode resultCode, Throwable e) {
        super(resultCode.getMessage(), e);
        this.errorMsg = resultCode.getMessage();
        this.errorCode = resultCode.getCode();
    }

    public MkException(ResultCode resultCode) {
        this.errorMsg = resultCode.getMessage();
        this.errorCode = resultCode.getCode();
    }
//...省略setter、getter
}
public enum ResultCode {
    //检查输入项不能为空错误码
    IS_NOT_BLANK_ERROR("999001", "请检查输入项,不能为空"),
    SUCCESS("000000", "success"),
    UNKNOW_ERROR("999999","系统未知异常"),
//省略其他错误码定义

    public String getCode() {
        return code;
    }

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

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    private String code;
    private String message;

    private ResultCode(String code, String message) {
        this.code = code;
        this.message = message;
    }

}

因为我们使用的是Spring框架,所以我们可以通过RestControllerAdvice对所有在最上层controller中进行统一拦截,在spring中实现这样的拦截需要自定义类继承自RestControllerAdvice,当然在spring4.0以后的版本可以通过@RestControllerAdvice注解来实现定义类,然后在类中实现异常处理,对于异常处理的方法需要添加@ExceptionHandler(xxxException.class)注解来表示该方法处理哪一类异常。

@RestControllerAdvice
public class MkExceptionHandler {
    private Logger logger = LoggerFactory.getLogger(getClass());

    private final static String NO_URL_FOUND = "404";

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(MkException.class)
    public MkResponse handleHOPException(MkException e){
        MkResponse r = new MkResponse();
        r.put("returnCode", e.getReturnCode());
        r.put("returnMsg", e.getReturnMsg());
        r.put("errorCode", e.getErrorCode());
        r.put("errorMsg", e.getErrorMsg());
        logger.error(new Date() + ": " + e.getMessage(), e);
        return r;
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public MkResponse handlerNoFoundException(Exception e) {
        logger.error(new Date() + ": " + e.getMessage(), e);
        return MkResponse.error(NO_URL_FOUND, "路径不存在,请检查路径是否正确");
    }

    //大家可以自己定义其他的异常处理

    @ExceptionHandler(Exception.class)
    public MkResponse handleException(Exception e){
        logger.error(new Date() + ": " + e.getMessage(), e);
        return MkResponse.error(e.getMessage());
    }
}

统一的异常处理是不是挺简单,并且也将正常的业务逻辑处理和异常处理的代码分离开了,并且返回的错误报文格式都是统一的,是不是整个工程更加清晰了。在TestController中有个exception方法,大家可以调用试试效果。

本文对应的github tag为v0.4,可以通过连接下载https://github.com/feiweiwei/MkFramework4java/releases/tag/v0.4,也可以通过git clone -b v0.4 https://github.com/feiweiwei/MkFramework4java.git

推荐阅读更多精彩内容