首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring Boot 全域異常處理完整指南:從局部到 @ControllerAdvice 實戰

     編輯:Java 綜合教學

Spring Boot 全域異常處理完整指南:從局部到 @ControllerAdvice 實戰

在 Spring Boot 應用開發中,統一的異常處理機制不僅能提升代碼可維護性,更能確保 API 回應格式一致性。本文將由淺入深,詳細解析 Spring Boot 中三種異常處理層級的實現方式、優先級規則及最佳實踐。

一、Controller 層級局部異常處理

當只需針對特定 Controller 處理異常時,可直接在該類別中使用 @ExceptionHandler 註解。

@RestController
@RequestMapping("/advice1")
@Api("測試 ControllerAdvice 與全域異常處理")
public class AdviceController {

    @GetMapping("/test1")
    public String test1() {
        throw new RuntimeException("advice1 - exception1");
    }

    @GetMapping("/test2")
    public String test2() {
        throw new RuntimeException("advice1 - exception2");
    }

    @ExceptionHandler(RuntimeException.class)
    public MyExceptionResponse exceptionHandler() {
        MyExceptionResponse resp = new MyExceptionResponse();
        resp.setCode(300);
        resp.setMsg("exception-Handler");
        return resp;
    }
}

關鍵點:

  • @ExceptionHandler 指定需處理的異常類型(支援多種異常類別)
  • 此處理方法僅在當前 Controller 生效
  • 回傳自定義響應物件時,若類別未標註 @RestController,需額外加上 @ResponseBody

二、全域異常處理:@ControllerAdvice 核心應用

@ControllerAdvice 是 Spring MVC 提供的切面增強類別,最常見用途即為全域異常處理。

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public MyExceptionResponse exceptionHandler(RuntimeException e, HttpServletResponse response) {
        MyExceptionResponse resp = new MyExceptionResponse();
        resp.setCode(300);
        resp.setMsg("全域異常處理: " + e.getMessage());
        // response.setStatus(600); // 可自訂 HTTP 狀態碼
        return resp;
    }
}

@ControllerAdvice 進階配置

透過註解屬性可精確控制掃描範圍:

  • @ControllerAdvice(annotations = RestController.class):僅掃描標註 @RestController 的類別
  • @ControllerAdvice(basePackages = {"com.xxx", "com.ooo"}):指定基礎包路徑
  • @ControllerAdvice(assignableTypes = {MyController.class}):指定具體類別

@ControllerAdvice 支援的回傳類型約定

回傳類型說明需搭配註解
String視為視圖名稱,進行頁面跳轉無
ModelAndView攜帶模型與視圖資訊無
自定義物件序列化為 JSON 回應@ResponseBody (或類別標註 @RestController)

三、異常處理優先級規則:就近原則

當同一異常被多層處理器覆蓋時,Spring 遵循「範圍越小優先級越高」的原則:

  1. 方法層級 @ExceptionHandler > 類別層級 @ExceptionHandler
  2. Controller 內部 @ExceptionHandler > @ControllerAdvice 全域處理器
  3. 精確匹配異常類別 > 父類別匹配(如 MyRuntimeException 優先於 RuntimeException)

實戰建議: 在 @ControllerAdvice 中定義通用異常處理(如參數驗證失敗、資源不存在、系統錯誤),在特定 Controller 中僅處理該業務特有的異常情況。

四、最佳實踐與擴展

1. 統一響應結構設計

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;
    private long timestamp = System.currentTimeMillis();
}

2. 區分業務異常與系統異常

// 業務異常:預期內的錯誤(如庫存不足、參數錯誤)
public class BusinessException extends RuntimeException {
    private final int code;
    public BusinessException(int code, String msg) { super(msg); this.code = code; }
}

// 系統異常:不可預期的錯誤(如資料庫連線失敗、第三方服務超時)
@ExceptionHandler(Exception.class)
@ResponseBody
public ApiResponse<Void> handleSystemError(Exception e, HttpServletRequest request) {
    log.error("系統異常: {}", request.getRequestURI(), e);
    return new ApiResponse<>(500, "系統內部錯誤", null);
}

3. 整合驗證框架異常處理

@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public ApiResponse<Map<String, String>> handleValidationError(MethodArgumentNotValidException e) {
    Map<String, String> errors = new HashMap<>();
    e.getBindingResult().getFieldErrors().forEach(err -> 
        errors.put(err.getField(), err.getDefaultMessage()));
    return new ApiResponse<>(400, "參數驗證失敗", errors);
}

五、參考資源深度閱讀

掌握 Spring Boot 異常處理機制,能讓你的應用在面對錯誤時更優雅、更可控。建議在專案初期即建立完善的異常處理體系,包含統一響應格式、異常分類、日誌記錄與監控告警,為系統穩定性奠定基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved