異常分類和層次結構
異常是分層次級別的,方法1,2,3代表異常層級。假如是方法3呼叫方法2,方法2呼叫方法1。
當方法1出現異常時,首先方法1會捕獲異常try catch,接著方法1的程式碼會決定怎麼處理異常(記錄日誌,或者修復異常假裝沒發生,或者返回客戶端錯誤)
假如不想處理異常,可以丟擲去給方法2,方法2繼續往上拋,也可以處理不處理,也可以往上拋。
如果能夠在伺服器內部正確處理異常,並且把異常糾正過來之後返回客戶端正確相應結果當然是好的,但是絕大多數情況下,流程就是不正確的了,沒有辦法返回正常的相應結果。這時候就需要返回一個異常資訊告訴服務端,我哪裡出錯了。
1:假如我在方法1捕獲異常,我處理了,但是按照理論,我要逐一往上拋錯。每一個方法要去捕獲處理下面的方法拋的異常。這樣程式碼是很繁瑣的,而且我們經常遺漏捕獲的異常。
2:有些異常我們是不能提前預知,或者由於經驗缺失我們沒有預料到這種型別異常錯誤。我們不會trycatch捕獲,但是又是侯不trycatch 會造成程式崩潰,這樣不好的。不捕獲就會一直存在。沒有捕獲就不去處理,不去處理就一直存在。
對於這2個情況我們需要全域性異常處理。對於我們API2件事情必須要做1.記錄日誌2.要有統一錯誤返回格式(錯誤碼和錯誤資訊),就在全域性異常處理做。如果全域性都不去處理,就會返回500狀態碼。(儘量不要有500)
全域性異常處理就是我們說的AOP(切面程式設計思維)通常我們使用框架比如說tp5就已經有全域性異常處理類,所以有時候我們想控制返回到客戶端的這樣的錯誤資訊格式,哪門我們就要重寫錯誤異常類。
我們把異常分為兩大類
1:由於使用者的行為導致的,如沒查詢到結果(通常應該返回空資料,而不應該視為異常,但是在rest服務裡對異常的定義並不是報錯,而是沒有返回你所期望的結果都可以視為異常)通常不需要記錄日誌,但是需要返回使用者具體資訊。比如使用者隨便輸入通不過你都記錄,這日記體積太大了。我們要選擇性記錄日誌。
2:伺服器自身異常:程式碼錯誤(1/0),呼叫外部介面錯誤。一定要記錄日誌排查錯誤,不需要返回原因。使用者不需要知道。
但是也不一定要完全按照要靈活,比如有個固定IP頻繁抓取介面相關內容,此時需要日誌記錄觀察一段時間。具體需要根據業務具體處理。異常就是不符合常規行為的都是異常。
如何區分:我們可以從結果反推,第一種異常有個硬性條件,需要向用戶返回資訊,我們需要定義一個類凡是屬於BaseException都是屬於第一種異常分類。我們只需要判斷由框架傳來的Exception是不是BaseException從而就可以對這樣兩種異常分類做一個型別區分。從正向理解,我們定義了BaseException類來代表我們的第一個分類。