當前問題
登錄功能和登錄校驗功能我們都實現了,下面我們學習下今天最后一塊技術點:異常處理。首先我們先來看一下系統出現異常之后會發生什么現象,再來介紹異常處理的方案。
我們打開瀏覽器,訪問系統中的新增部門操作,系統中已經有了 "就業部" 這個部門,我們再來增加一個就業部,看看會發生什么現象。
點擊確定之后,窗口關閉了,頁面沒有任何反應,就業部也沒有添加上。 而此時,大家會發現,網絡請求報錯了。
狀態碼為500,表示服務器端異常,我們打開idea,來看一下,服務器端出了什么問題。
上述錯誤信息的含義是,dept部門表的name字段的值 就業部 重復了,因為在數據庫表dept中已經有了就業部,我們之前設計這張表時,為name字段建議了唯一約束,所以該字段的值是不能重復的。
而當我們再添加就業部,這個部門時,就違反了唯一約束,此時就會報錯。
我們來看一下出現異常之后,最終服務端給前端響應回來的數據長什么樣。
響應回來的數據是一個JSON格式的數據。但這種JSON格式的數據還是我們開發規范當中所提到的統一響應結果Result嗎?顯然并不是。由于返回的數據不符合開發規范,所以前端并不能解析出響應的JSON數據。
接下來我們需要思考的是出現異常之后,當前案例項目的異常是怎么處理的?
? ? ● 答案:沒有做任何的異常處理
當我們沒有做任何的異常處理時,我們三層架構處理異常的方案:
Mapper接口在操作數據庫的時候出錯了,此時異常會往上拋(誰調用Mapper就拋給誰),會拋給service。
service 中也存在異常了,會拋給controller。
而在controller當中,我們也沒有做任何的異常處理,所以最終異常會再往上拋。最終拋給框架之后,框架就會返回一個JSON格式的數據,里面封裝的就是錯誤的信息,但是框架返回的JSON格式的數據并不符合我們的開發規范。
解決方案
那么在三層構架項目中,出現了異常,該如何處理?
? ? ● 方案一:在所有Controller的所有方法中進行try…catch處理
? ? ? ? ○ 缺點:代碼臃腫(不推薦)
? ? ● 方案二:全局異常處理器
? ? ? ? ○ 好處:簡單、優雅(推薦)
全局異常處理器
我們該怎么樣定義全局異常處理器?
定義全局異常處理器非常簡單,就是定義一個類,在類上加上一個注解@RestControllerAdvice,加上這個注解就代表我們定義了一個全局異常處理器。
在全局異常處理器當中,需要定義一個方法來捕獲異常,在這個方法上需要加上注解@ExceptionHandler。通過@ExceptionHandler注解當中的value屬性來指定我們要捕獲的是哪一類型的異常。
@RestControllerAdvice
public class GlobalExceptionHandler {//處理異常@ExceptionHandler(Exception.class) //指定能夠處理的異常類型public Result ex(Exception e){e.printStackTrace();//打印堆棧中的異常信息//捕獲到異常之后,響應一個標準的Resultreturn Result.error("對不起,操作失敗,請聯系管理員");}
}
@RestControllerAdvice = @ControllerAdvice + @ResponseBody
————————————————————————————————————————
處理異常的方法返回值會轉換為json后再響應給前端
重新啟動SpringBoot服務,打開瀏覽器,再來測試一下添加部門這個操作,我們依然添加已存在的 "就業部" 這個部門:
此時,我們可以看到,出現異常之后,異常已經被全局異常處理器捕獲了。然后返回的錯誤信息,被前端程序正常解析,然后提示出了對應的錯誤提示信息。
以上就是全局異常處理器的使用,主要涉及到兩個注解:
? ? ● @RestControllerAdvice //表示當前類為全局異常處理器
? ? ● @ExceptionHandler //指定可以捕獲哪種類型的異常進行處理