java異常體系和業務處理


一、java異常體系

先看Java異常體系圖:

所有異常類的父類為Throwable類,兩個直接子類為Error和Exception分別表示錯誤和異常。

1、Error類

Error是程序無法處理的錯誤,它是由JVM產生和拋出的,比如OutOfMemoryError、ThreadDeath等。這些異常發生時,Java虛擬機(JVM)一般會選擇線程終止。

2、Exception類

Exception是程序本身可以處理的異常,這種異常分兩大類運行時異常(Unchecked Exception)和非運行時異常(Checked Exception)。程序中應當盡可能去處理這些異常。

RuntimeException(Unchecked Exception):即可以編譯通過,一般由程序的邏輯錯誤引起,開發過程中應盡量避免。例如:NullPointerException,IndexOutOfBoundsException等。自定義異常一般繼承此類。

RuntimeException以外的異常(checked Exception):編譯器在編譯階段進行處理,程序必須處理此類異常否則無法通過編譯,如IOException、SQLException等。

二、異常的捕獲和處理

異常的捕獲通過try、catch、finally三個關鍵字,三個語句塊均不能單獨使用,三者可以組成 try...catch...finally、try...catch、try...finally三種結構,catch語句可以有一個或多個,finally語句只能一個

1、普通無異常:

public class TestDemo {
	 public static void main(String[] args) {
	        String result = GetString();
	        System.out.print(result);

	    }
    public static String GetString(){
        try
        {
            System.out.print("GetString():try\n");
            return "GetString()返回值\n";
        }
        catch (Exception e)
        {
            System.out.print("GetString():catch\n");
            return "GetString()返回值";
        }
        finally
        {
            System.out.print("GetString():finally\n");
        }
        //return "這里是方法底部返回值";
    }
}

  運行結果:

整個執行順序如下:執行順序是try=>finally=>return

2、出現異常調用情況

public class TestDemo {
	 public static void main(String[] args) {
	        String result = GetString();
	        System.out.print(result);
	    }
    public static String GetString(){
        try
        {
            System.out.print("GetString():try\n");
            int i = 0;
        	int var = 1 / i ;
        	System.out.print("執行GetString():1/i\n");
            return "GetString()try 返回值\n";
        }
        catch (Exception e)
        {
            System.out.print("GetString():catch\n");
            return "GetString()catch 返回值";
        }
        finally
        {
            System.out.print("GetString():finally\n");
        }
        //return "這里是方法底部返回值";
    }
}

  執行結果:

整個執行順序如下:try=>catch=>finally=>catch return

可以確定:

1)不論出不出現異常都會執行finally代碼塊

2)在try模塊中出現異常后,異常代碼后續流程都不會繼續執行

3、try、catch、finally模塊中進行賦值

public class TestDemo {
	 public static void main(String[] args) {
	        String result = GetString();
	        System.out.print(result);
	    }
    public static String GetString(){
    	String var = "";
        try
        {
            var = "try var值";
        	System.out.print("執行GetString():var\n");
            return var;
        }
        catch (Exception e)
        {
            System.out.print("GetString():catch\n");
            return "GetString()catch 返回值";
        }
        finally
        {
        	var = "finally var值";
            System.out.print("GetString():finally\n");
        }
    }
}

  執行結果:

通過執行結果可以看到,在finally中對var進行賦值,雖然程序執行了finally模塊,但是最終不會影響var的值,var的值還是在try模塊中賦值內容。

結論:雖然finally方法會被執行但是返回結果不會被改變,也就是finally是在return之后執行的,try模塊會先把返回結果先保存起來,然后不管finally代碼執行了什么,都不會影響到返回結果,等finally執行完成在返回結果。

三、業務如何定義異常

業務中需要按照一定的規范來定義異常,這樣有利於系統管理業務異常。

通過上面繼承圖可以看出,所有service都會繼承BaseExcepion,BaseException最終通過RuntimeException來實現。

而在實際的業務中需要准確定位異常歸屬的服務和具體類型,這樣就可以在對異常日志進行監控時有區分的進行不同的處理(比如重要的帳務或者渠道服務進行較高優先級的提醒或者自處理)。

所以可以在BaseException通過系統定義的code,code通過兩個部分來組成:不同的service定義的值和同一個service中具體異常類型值。

public class BaseException extends RuntimeException {

    private String code;

    public BusinessException() {
        super();
    }

    public BusinessException(String code, String message) {
        super(message);
        this.code = code;
    }

    public String getCode() {
        return code;
    }

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

    /**
     * 獲取異常編碼
     * @param sysCode 系統編號枚舉
     * @param exceptionType 異常類型枚舉
     * @param exceptionCode 異常順序碼
     * @return String 異常編碼
     */
    protected static String getExceptionCode(SysCode sysCode, ExceptionType exceptionType, String exceptionCode) {

        if (StringUtil.isEmpty(exceptionCode) || StringUtil.length(exceptionCode) != 4) {
            throw new BusinessException("00000000", "異常編碼不符規范");
        }

        return new StringBuilder(sysCode.getCode()).append(exceptionType.getCode()).append(exceptionCode).toString();
    }

    public BusinessException print(String message) {
        logger.error("BusinessException Code:{};Message:{};OtherMessage:{}", this.code, super.getMessage(), message);
        return this;
    }

  在serviceA中通過調用定義異常類型ORDER_PARAM_NULL,本身ServiceA自帶code:SysCode.SER_A,再和定義的1001進行拼接得到最終的該異常在整個系統中的異常code。

public class ServiceAException extends BusinessException {
    public static FeeException ORDER_PARAM_NULL = new ServiceAException(getExceptionCode( "1001"),
            "關鍵參數為空");    
    public static String getExceptionCode(String exceptionCode) {
        return getExceptionCode(SysCode.SER_A/*這里定義serviceA的系統code值*/,  exceptionCode);
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM