目錄
一.為什么引入全局異常處理器(目前項目碰到了什么問題)?
1.問題描述
2.與預期的差別
3.解決方案
二.解決上述問題
1.定義【業務異常類】
2.在serviceImpl層,手動拋出【違反唯一性約束】這個異常
3.定義【全局異常處理器】
4.修改userController層的代碼
三.展示效果
四.重點理解【全局異常處理器】的優點
1.項目引入了全局異常處理器以后,就不用在controller里面判斷insert語句的影響行數了
2.引入全局異常處理器后,可以使得請求異常時的響應數據可讀性非常強。
3.引入全局異常處理器后,后端產生異常時不會在控制臺輸出大片異常信息。
4.總結大致流程
結語
一.為什么引入全局異常處理器(目前項目碰到了什么問題)?
1.問題描述
????????我們在添加一個系統用戶時,要求用戶名(username字段)必須是唯一的,即不能重復。如果重復了,那么insert語句不會返回0(之前我們是這么認為的),而是直接令后端報錯。如下:
使用apiFox添加一個系統用戶:?
去后端控制臺查看報錯:
可見此時是因為違反了user表的username字段的唯一約束(unique)。
2.與預期的差別
????????我的初衷是:添加一個系統用戶時,如果添加成功,就返回影響行數1;如果添加失敗,就返回影響行數0。?
? ? ? ? 這樣就能在controller層中,根據影響行數來決定返回給前端什么響應體。
? ? ? ? 如下:
? ? ? ? userServiceImpl層:
? ? ? ? userController層:?
? ? ? ? 重點來了:上述所預想的一切,都不成立。因為當insert語句執行失敗時,根本就不返回影響行數0,而是直接使后端崩塌,響應給前端的數據也是可讀性極差。?
3.解決方案
? ? ? ? ?此時就需要定義【業務異常】和【全局異常處理器】來包容上述的錯誤。
????????就好比insert語句執行失敗時,扔出一顆炸彈,但沒關系,我們直接使用全局異常處理器,來吸收即可。
二.解決上述問題
1.定義【業務異常類】
? ? ? ? 該業務異常類,就包括我們上面提到的違反了唯一約束的這種異常。
? ? ? ? 而且以后我們項目中出現了其他的業務異常,也可以用該類來接收。
? ? ? ? 第一步:創建Exception目錄,用來存放自定義異常類和全局異常處理器。
? ? ? ? 第二步:在?Exception目錄下,創建【業務異常類】。
2.在serviceImpl層,手動拋出【違反唯一性約束】這個異常
3.定義【全局異常處理器】
全局異常處理器,得益于spring。我們可以在全局異常處理器中,進行捕獲某種異常并進行對應操作。從而來優化響應數據、防止后端崩塌(其實是美化后端控制臺)。
在exception目錄下,創建全局異常處理器。
package com.neuedu.his.Exception;import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;@ControllerAdvice//該注解可以自動捕獲我們剛才拋出的異常
public class GlobalExceptionHandler {//處理自定義異常:【業務異常BusinessException】@ExceptionHandler(BusinessException.class)//專門處理業務異常類BusinessException@ResponseBody//表示我們要將該方法的返回值轉為JSON格式返回給前端public ResponseEntity<Map<String, Object>> handleBusinessException(BusinessException e){Map<String, Object> response = new HashMap<>();response.put("code", 409);response.put("message", e.getMessage());return new ResponseEntity<>(response, HttpStatus.CONFLICT);}//處理其他異常@ExceptionHandler(Exception.class)@ResponseBodypublic ResponseEntity<Map<String, Object>> handleException(Exception e){Map<String, Object> response = new HashMap<>();response.put("code", 500);response.put("message", "系統內部錯誤,請稍后重試");return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);}
}
4.修改userController層的代碼
三.展示效果
成功的情況:
異常情況1:違反了數據庫字段唯一性(業務異常)
異常情況2:其他異常
四.重點理解【全局異常處理器】的優點
1.項目引入了全局異常處理器以后,就不用在controller里面判斷insert語句的影響行數了
????????如下:我們在userController層中,沒有判斷insert語句的影響行數的情況下,就返回了成功信息。
? ? ? ? 這是因為,代碼能走到這里,說明userService沒有拋出任何異常,也就間接說明了我們的添加用戶業務沒有任何問題,因此結果肯定是添加成功,因此就可以直接返回成功信息。
? ? ? ? 因此以后我們項目引入全局異常處理器以后,在controller層可以直接調用完service層后直接返回成功信息。
2.引入全局異常處理器后,可以使得請求異常時的響應數據可讀性非常強。
引入全局異常處理器之前,請求異常時的響應信息:
引入全局異常處理器之后,請求異常時的響應信息:
如下圖:這兩種異常請求下的響應數據,可讀性都十分強,比原來的大坨字母強多了。
3.引入全局異常處理器后,后端產生異常時不會在控制臺輸出大片異常信息。
引入全局異常處理器之前,產生異常時控制臺的樣貌:
引入全局異常處理器之后,產生異常時控制臺的樣貌:
4.總結大致流程
①定義【自定義異常類】和【全局異常處理器】
②手動在serviceIml層拋出異常
③【全局異常處理器】自動捕獲上面拋出的異常,并進行響應消息處理。
④如果serviceImpl層沒拋出異常,則響應消息由controller層返回;
? ? 如果serviceImpl層拋出了一場,則響應消息由【全局異常處理器】的某個方法返回。
結語
以上就是在項目中,引入【全局異常處理器】的原因、做法、優點。
喜歡本篇文章的話,可以留個免費的關注呦~~