Spring Boot 異常處理

霍格沃兹测试开发学社發表於2024-03-27
  • Java 異常類
    首先讓我們簡單瞭解或重新學習下 Java 的異常機制。

Java 內部的異常類 Throwable 包括了 Exception 和 Error 兩大類,所有的異常類都是 Object 物件。

Error 是不可捕捉的異常,通俗的說就是由於 Java 內部 JVM 引起的不可預見的異常, Java 虛擬機器會選擇終止執行緒。如 OutOfMemoryError ,就是 Java 虛擬機器執行過程中出現記憶體資源錯誤丟擲的。

Excetpion 異常是程式本身引起的,它又分為執行時異常 RuntimeException,和非執行時(編譯時)IOException 等異常。如除數為零時引發的 ArrayIndexOutOfBoundException 異常就是執行時異常。非執行異常都是可查可捕捉的。Java 編譯器會告訴程式他錯了,錯在哪裡,正確的建議什麼。我們可以透過 throws 配合 try-catch 來處理。

  • Java 異常處理機制
    在 Java 應用程式中,異常處理機制為:丟擲異常,捕捉異常。

丟擲異常:當一個方法出現錯誤引發異常時,方法建立異常物件並交付執行時系統,異常物件中包含異常型別和出現異常時的程式執行時資訊。執行時系統負責尋找處置異常的程式碼並執行。

捕獲異常:在方法丟擲異常之後,執行時系統將轉為尋找合適的異常處理器(Exception Handler)。潛在的異常處理器是異常發生時依次存留在呼叫棧中的方法的集合。

當異常處理器能處理的異常型別與方法丟擲的異常型別相符時,即為合適的異常處理器。執行時系統從發生異常的方法開始,依次回查呼叫棧中的方法,直至找到含有合適異常處理器的方法並執行。
當執行時系統遍歷呼叫棧而未找到合適 的異常處理器,則執行時系統終止。同時,意味著 Java 程式的終止。

  • Spring Boot 異常處理
    Spring Boot 的所有異常處理都基於 java 的。

在 Spring Boot 應用程式中,通常統一處理異常的方法有 使用註解處理 RestControllerAdvice
本示例主要目的處理我們日常 Spring Boot 中的異常處理

在 Web 專案中透過 ControllerAdvice、RestControllerAdvice 實現全域性異常處理

ControllerAdvice 和 RestControllerAdvice 的區別 相當於 Controller 和 RestController 的區別。

程式碼示例

  • GlobalExceptionHandler.java
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler({Exception.class})
    public Object exceptionHandler(Exception e){
        Map<String,Object> map=new HashMap<>();
        map.put("status",-1);
        map.put("msg",e.getLocalizedMessage());
        return map;
    }
}

  • 配置介紹
    RestControllerAdvice:全域性捕獲異常,異常集中處理,更好的使業務邏輯與異常處理剝離開,定義在類上

ExceptionHandler:統一處理某一類異常,宣告該方法用於捕獲 value 所指的型別的異常(注意:當該異常的子父類都被宣告時,按照先子後父的順序進行捕獲)

ResponseStatus:將某種異常對映為 HTTP 狀態碼,可用在方法上,也可以用在類上(自定義執行時異常類)。

  • HogwartsTestUserController.java
    在 HogwartsTestUserController.java 新增一個 error 介面
/**
     * 模擬丟擲異常
     * */
    @GetMapping("/error")
    public Object err(){
        throw new RuntimeException("丟擲一個異常");
    }

GET http://127.0.0.1:8081/api/user/users/3 正常返回

{
    "id": 3,
    "name": "HogwartsTest2",
    "pwd": "HogwartsTest2"
}

GET http://127.0.0.1:8081/api/user/error 丟擲異常,並給出提示資訊

相關文章