springBoot自定義全局異常捕獲Exception 非傳統做法

在開始之前還是帶著問題為啥要自定義異常,我的這種自定義異常方案跟大部分方案有何不同,肯定有跟我類似的,但是我是沒發現。。。

首先是為什麼要自定義異常,任何程序都不能保證不出bug,尤其是web程序,如果出現異常沒有友好的提示是不行的,直接返回後臺的一堆500錯誤代碼也是不安全的,而且異常有時候也不可控,比如突然數據庫連接中斷了,突然除數為0了,突然空指針異常了,等各種,程序員呢也是人,不可能任何邏輯都寫得天衣無縫不出一點bug,程序報錯有bug不要緊,但如何友好的輸出異常並提示這也是系統設計比較重要的事情。

相信很多碼友都用過各種系統或者軟件,用著用著就點不動了,也不提示錯誤,也沒任何反應,到底是啥問題也不知道,是不是很惱火呢?對於普通用戶來說體驗更差了,這就是沒做好異常處理的問題,無論後端發生任何問題都需要給予操作者一個提示,這才是體驗好的系統。

我這裡的自定義異常方案和傳統的異常自定方案有著很大的不同,包括我這麼多年參與的系統都是用傳統的自定義異常方案和提示,舉一個例子,比如第一個用戶在前端要刪除一條記錄,在當時查詢的時候,這條記錄是可以被刪除的,有刪除按鈕,可是在這時有第二個人對這條記錄進行了鎖定,也就是不允許刪除了,第一個用戶按下了刪除按鈕後臺就會提示此用戶已經鎖定無法刪除,這種提示只有後端才能返回,或者返回自定義狀態碼,傳統的自定義異常就是直接請求200正常,然後返回一個json對象{code: 622, msg: "此用戶已經鎖定", data: {}}這是傳統的方式,相信很多碼友都是這樣返回的,但是這個返回有一個很大的弊端,就是請求狀態http狀態是200成功,前端如果用ajax或者axios請求,是不能在ajax異常裡面捕獲的而得在success中做if判斷,判斷code是多少,然後再取msg提示,是不是很不優雅,雖然可以對ajax等做攔截封裝,匹配code提示,但是也不合理。

而且這種還有一個弊端就是,後端controller返回的數據格式得用一個模型統一封裝,也就是controller裡面的每個方法的返回值都得封裝成前端統一的格式,而且很多系統都是這樣做的,如果在做微服務調用就發現更不合理了,我認為異常是異常但不能放在200的請求成功裡面進行提示,包括已知異常和未知異常,都不應該放在請求成功而且返回什麼code,msg這種json串然後給前端判斷,都是不合理的。

下面就說說我的設計方式

springBoot自定義全局異常捕獲Exception 非傳統做法

從圖中可以看到後臺報錯,不管是已知和未知錯誤都會拋出異常跟正確的返回結果是完全不一樣的,而且http狀態碼也不是200,這樣前端ajax或者axios的異常攔截就能直接處理,而無需做if判斷,而正確的狀態碼200則只返回需要的數據,json格式,不添加任何的什麼code,msg等,我認為是無意義的,code和msg應該是屬於後端返回的提示應該是屬於異常的一部分,都已經請求200了還給提示幹嘛?有人可能會說,那保存成功,刪除失敗,這種提示呢?這種提示也不應該放在200裡面,像保存成功如果後端請求200前端就可以直接提示保存成功了,也不需要後端返回,直接看狀態碼就行了,如果是刪除失敗後端應該是直接拋出異常,那狀態碼就不是200了,直接就被前端異常機制捕獲了,多合理。

下面就具體實踐下怎麼在springBoot中實現這種方案

1、在項目中創建一個exception包,新建三個自定義異常類

springBoot自定義全局異常捕獲Exception 非傳統做法

全局異常

springBoot自定義全局異常捕獲Exception 非傳統做法

資源找不到異常

springBoot自定義全局異常捕獲Exception 非傳統做法

警告提示

2、新建一個處理器包,handler,用於rest異常的處理

springBoot自定義全局異常捕獲Exception 非傳統做法

rest異常捕獲和自定義返回結果

3、在model包中新建一個ErrorModel和一個枚舉類ErrorStatus

springBoot自定義全局異常捕獲Exception 非傳統做法

錯誤模型

springBoot自定義全局異常捕獲Exception 非傳統做法

錯誤狀態

4、修改UserServiceImpl業務實現類,拋出自定義異常

springBoot自定義全局異常捕獲Exception 非傳統做法

使用自定義異常

5、修改UserController對異常進行捕獲

springBoot自定義全局異常捕獲Exception 非傳統做法

6、啟動項目進行測試

springBoot自定義全局異常捕獲Exception 非傳統做法

如果為1就給與提示異常

springBoot自定義全局異常捕獲Exception 非傳統做法

springBoot自定義全局異常捕獲Exception 非傳統做法

如果為3,除數不能為0,全局異常自動捕獲

springBoot自定義全局異常捕獲Exception 非傳統做法

如果id存在則直接返回結果

7、文章源碼地址

關注+轉發後私信我源碼地址,感謝支持

這樣設計,只要是200那就是前端想要的數據,不是200那就是異常,前端就很方便處理,而且後端也不需要對返回結果封裝,不僅方便還提高開發效率,如果有啥更好的方法可以在評論區留言,如果我這個設計有啥滿足不了需求的也可以告訴我。


分享到:


相關文章: