架構之全局錯誤異常定義

異常簡介

說明

一個開發框架少不了異常處理機制,讓所有的錯誤集中在一個地方處理,在業務代碼開發的時候,往外拋就可以了,由上層統一攔截處理、返回給調用方。這裏我們使用了自定義錯誤碼,並將錯誤碼定義在了錯誤碼枚舉類中,當然如果你的系統比較龐大,錯誤碼非常多,並且要實現錯誤碼的動態調整,那麼也可以將錯誤碼存在數據庫中,啓動後放到內存緩存,這裏爲了方便大家理解只是提前將錯誤碼定義在了枚舉類中。

UML圖

自定義異常異常處理

異常定義

錯誤碼定義

通過實現此接口擴展應用程序中的錯誤代碼

public interface ErrorCodeI {

    public String getErrCode();

    public String getErrDesc();

}

基礎錯誤碼定義

定義3個基本錯誤代碼

public enum BasicErrorCode implements ErrorCodeI {

    BIZ_ERROR("BIZ_ERROR" , "通用的業務邏輯錯誤"),

    ZCB_ERROR("ZCB_FRAMEWORK_ERROR" , "ZCB框架錯誤"),

    SYS_ERROR("SYS_ERROR" , "未知的系統錯誤" );

    private String errCode;

    private String errDesc;

    private BasicErrorCode(String errCode, String errDesc){
        this.errCode = errCode;
        this.errDesc = errDesc;
    }

    @Override
    public String getErrCode() {
        return errCode;
    }

    @Override
    public String getErrDesc() {
        return errDesc;
    }
}

基礎異常信息定義

基異常是所有異常的父級,需要繼承運行時異常RuntimeException

public abstract class BaseException extends RuntimeException{

    private static final long serialVersionUID = 1L;
    
    private ErrorCodeI errCode;
    
    public BaseException(String errMessage){
        super(errMessage);
    }
    
    public BaseException(String errMessage, Throwable e) {
        super(errMessage, e);
    }
    
    public ErrorCodeI getErrCode() {
        return errCode;
    }
    
    public void setErrCode(ErrorCodeI errCode) {
        this.errCode = errCode;
    }
    
}

框架異常定義

擴展框架的基礎結構異常

public class ZCBException extends BaseException {
    
    private static final long serialVersionUID = 1L;
    
    public ZCBException(String errMessage){
        super(errMessage);
        this.setErrCode(BasicErrorCode.ZCB_ERROR);
    }
    
    public ZCBException(String errMessage, Throwable e) {
        super(errMessage, e);
        this.setErrCode(BasicErrorCode.ZCB_ERROR);
    }
}

通用業務異常定義

擴展框架的業務已知異常

public class BizException extends BaseException {

    private static final long serialVersionUID = 1L;

    public BizException(String errMessage){
        super(errMessage);
        this.setErrCode(BasicErrorCode.BIZ_ERROR);
    }

    public BizException(ErrorCodeI errCode, String errMessage){
        super(errMessage);
        this.setErrCode(errCode);
    }

    public BizException(String errMessage, Throwable e) {
        super(errMessage, e);
        this.setErrCode(BasicErrorCode.BIZ_ERROR);
    }
}

系統異常定義

擴展框架系統意外異常

public class SysException extends BaseException {

    private static final long serialVersionUID = 4355163994767354840L;

    public SysException(String errMessage){
        super(errMessage);
        this.setErrCode(BasicErrorCode.SYS_ERROR);
    }

    public SysException(ErrorCodeI errCode, String errMessage) {
        super(errMessage);
        this.setErrCode(errCode);
    }

    public SysException(String errMessage, Throwable e) {
        super(errMessage, e);
        this.setErrCode(BasicErrorCode.SYS_ERROR);
    }

    public SysException(String errMessage, ErrorCodeI errorCode, Throwable e) {
        super(errMessage, e);
        this.setErrCode(errorCode);
    }
}

異常處理

異常處理接口定義

ExceptionHandlerI提供了一個後門,應用程序可以覆蓋默認的異常處理

public interface ExceptionHandlerI {
    public void handleException(Command cmd, Response response, Exception exception);
}

異常處理工廠

這裏提供一種擴展機制,如果自己有實現異常處理機制,則執行自定義的異常處理,沒有就走默認的異常處理機制。

public class ExceptionHandlerFactory {

    public static ExceptionHandlerI getExceptionHandler(){
        try {
            return ApplicationContextHelper.getBean(ExceptionHandlerI.class);
        }
        catch (NoSuchBeanDefinitionException ex){
            return DefaultExceptionHandler.singleton;
        }
    }

}

默認異常處理

默認捕獲異常並打印日誌,並在對應的返回信息返回錯誤碼。

public class DefaultExceptionHandler implements ExceptionHandlerI {

    private Log logger = LogFactory.getLog(ExtensionExecutor.class);

    public static DefaultExceptionHandler singleton = new DefaultExceptionHandler();

    @Override
    public void handleException(Command cmd, Response response, Exception exception) {
        buildResponse(response, exception);
        printLog(cmd, response, exception);
    }

    private void printLog(Command cmd, Response response, Exception exception) {
        if(exception instanceof BaseException){
            //biz exception is expected, only warn it
            logger.warn(buildErrorMsg(cmd, response));
        }
        else{
            //sys exception should be monitored, and pay attention to it
            logger.error(buildErrorMsg(cmd, response), exception);
        }
    }

    private String buildErrorMsg(Command cmd, Response response) {
        return "Process ["   cmd   "] failed, errorCode: "
                  response.getErrCode()   " errorMsg:"
                  response.getErrMessage();
    }

    private void buildResponse(Response response, Exception exception) {
        if (exception instanceof BaseException) {
            ErrorCodeI errCode = ((BaseException) exception).getErrCode();
            response.setErrCode(errCode.getErrCode());
        }
        else {
            response.setErrCode(BasicErrorCode.SYS_ERROR.getErrCode());
        }
        response.setErrMessage(exception.getMessage());
        response.setSuccess(false);
    }
}

異常處理調用

在最上層框架進行調用,爲異常處理的總入口。

    public Response invoke(Command command) {
        Response response = null;
        try {
            preIntercept(command);
            response = commandExecutor.execute(command);  
        }
        catch(Exception e){
            response = getResponseInstance(command);
            response.setSuccess(false);
            ExceptionHandlerFactory.getExceptionHandler().handleException(command, response, e);
        }
        finally {
            //make sure post interceptors performs even though exception happens
            postIntercept(command, response);
        }          
        return response;
    }

使用場景

系統異常

    public static<T> T getBean(Class<T> targetClz){
        T beanInstance = null;
        //優先按type查
        try {
            beanInstance = (T) applicationContext.getBean(targetClz);
        }catch (Exception e){
        }
        //按name查
        if(beanInstance == null){
            String simpleName = targetClz.getSimpleName();
            //首字母小寫
            simpleName = Character.toLowerCase(simpleName.charAt(0))   simpleName.substring(1);
            beanInstance = (T) applicationContext.getBean(simpleName);
        }
        if(beanInstance == null){
            new SysException(BasicErrorCode.SYS_ERROR, "Component "   targetClz   " can not be found in Spring Container");
        }
        return beanInstance;
    }

業務異常

 public static void notNull(Object object, ErrorCodeI errorCode, String message) {
        if (object == null) {
            throw new BizException(errorCode, message);
        }
    }

自定義異常

 private void checkNull(BizScenario bizScenario){
        if(bizScenario == null){
            throw new ZCBException("BizScenario can not be null for extension");
        }
    }

個人網站:http://www.cnzcb.cn

本文由博客一文多發平臺 OpenWrite 發佈!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章