最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot全局異常處理保姆級教程從入門到實戰(zhàn)(看完秒懂)

 更新時間:2025年06月26日 11:34:02   作者:碼不停蹄的玄黓  
本文講解SpringBoot全局異常處理,通過@RestControllerAdvice集中處理異常,統(tǒng)一響應(yīng)格式,提升代碼簡潔性與安全性,涵蓋業(yè)務(wù)異常、參數(shù)校驗及系統(tǒng)異常處理,避免敏感信息泄露,并提供日志記錄與狀態(tài)碼自定義等進階技巧,感興趣的朋友跟隨小編一起看看吧

在Spring Boot開發(fā)中,你是否遇到過這樣的困擾?
每個Controller方法都要寫一堆try-catch塊,代碼冗余到懷疑人生;前端抱怨接口返回格式不統(tǒng)一,有的返回JSON,有的返回HTML;系統(tǒng)報錯時直接把數(shù)據(jù)庫異常堆棧暴露給用戶,安全隱患拉滿……

別慌!今天這篇文章帶你徹底搞定全局異常處理,用一行代碼替代所有重復(fù)的try-catch,讓異常處理變得優(yōu)雅又高效!

一、為什么要學(xué)全局異常處理?看完你就懂了!

1.1 痛點驅(qū)動

想象一下:你有10個Controller,每個都要處理NullPointerException、IllegalArgumentException,甚至還要處理業(yè)務(wù)自定義的“用戶不存在”異常……代碼重復(fù)率高達80%,改個返回格式就得改10個地方,這不是在寫代碼,是在“復(fù)制粘貼”!

1.2 核心價值

  • 代碼簡潔:只需一個類集中處理所有異常,告別重復(fù)try-catch。
  • 響應(yīng)統(tǒng)一:前端收到的永遠是{code: 200, msg: "成功", data: ...}格式,解析無壓力。
  • 安全可控:系統(tǒng)異常(如數(shù)據(jù)庫崩潰)不暴露堆棧,業(yè)務(wù)異常(如“余額不足”)明確提示用戶。
  • 日志友好:異常信息集中記錄,排查問題不用翻遍各個Controller。

二、Spring Boot全局異常處理的核心實現(xiàn)

Spring Boot提供了超好用的@RestControllerAdvice注解(@ControllerAdvice+@ResponseBody的組合),專門用于前后端分離場景的全局異常處理。咱們直接上干貨!

2.1 第一步:定義統(tǒng)一響應(yīng)格式

前端需要“標準化”的錯誤提示,所以先定義一個通用的Result類,所有接口返回值都用它包裝。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result<T> {
    private Integer code;  // 狀態(tài)碼(200=成功,400=參數(shù)錯誤,500=系統(tǒng)錯誤)
    private String msg;    // 提示信息
    private T data;        // 業(yè)務(wù)數(shù)據(jù)(可選)
    // 快速構(gòu)建成功響應(yīng)(帶數(shù)據(jù))
    public static <T> Result<T> success(T data) {
        return new Result<>(200, "操作成功", data);
    }
    // 快速構(gòu)建失敗響應(yīng)(自定義code和msg)
    public static <T> Result<T> error(Integer code, String msg) {
        return new Result<>(code, msg, null);
    }
}

2.2 第二步:編寫全局異常處理器

@RestControllerAdvice標記一個類,Spring Boot會自動掃描并攔截所有Controller的異常。重點是用@ExceptionHandler指定要處理的異常類型。

場景1:處理業(yè)務(wù)自定義異常(比如“用戶不存在”)

業(yè)務(wù)中經(jīng)常需要拋“用戶不存在”、“訂單已支付”這類異常,咱們可以自定義異常類,然后在全局處理器里捕獲。

步驟1:定義業(yè)務(wù)異常類

// 自定義業(yè)務(wù)異常(繼承RuntimeException,方便在Service層拋出)
public class BusinessException extends RuntimeException {
    private Integer code;  // 業(yè)務(wù)錯誤碼(如4001=用戶不存在)
    public BusinessException(Integer code, String msg) {
        super(msg);
        this.code = code;
    }
    public Integer getCode() {
        return code;
    }
}

步驟2:全局捕獲業(yè)務(wù)異常

@RestControllerAdvice
public class GlobalExceptionHandler {
    // 處理業(yè)務(wù)異常(比如用戶不存在)
    @ExceptionHandler(BusinessException.class)
    public Result<?> handleBusinessException(BusinessException e) {
        return Result.error(e.getCode(), e.getMessage());
    }
}
場景2:處理參數(shù)校驗異常(@Valid校驗失?。?/h5>

@Valid校驗請求參數(shù)時,參數(shù)不合法會拋MethodArgumentNotValidException,咱們可以提取錯誤信息,友好提示用戶。

// 全局處理參數(shù)校驗異常(@RequestBody參數(shù)校驗失敗)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<?> handleValidationException(MethodArgumentNotValidException e) {
    // 提取所有校驗失敗的字段信息(比如"用戶名不能為空")
    String errorMsg = e.getBindingResult().getFieldErrors().stream()
            .map(FieldError::getDefaultMessage)
            .collect(Collectors.joining(";"));
    return Result.error(400, "參數(shù)校驗失?。? + errorMsg);
}
場景3:處理系統(tǒng)未知異常(兜底方案)

數(shù)據(jù)庫崩潰、空指針等系統(tǒng)級異常,必須捕獲并返回通用提示,同時記錄完整日志(避免暴露敏感信息)。

// 全局處理其他未捕獲的異常(系統(tǒng)級錯誤)
@ExceptionHandler(Exception.class)
public Result<?> handleSystemException(Exception e) {
    // 記錄完整異常堆棧(生產(chǎn)環(huán)境必加!)
    log.error("系統(tǒng)發(fā)生未知異常,請求路徑:{}", getRequestPath(), e);
    // 返回友好提示(前端看到的是"服務(wù)器繁忙,請稍后再試")
    return Result.error(500, "服務(wù)器繁忙,請稍后再試");
}
// 輔助方法:獲取當前請求路徑(需要spring-web依賴)
private String getRequestPath() {
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    return attributes == null ? "" : attributes.getRequest().getRequestURI();
}

2.3 第三步:在業(yè)務(wù)中拋異常,測試效果!

現(xiàn)在,在Service層拋出自定義異常,看看是否被全局處理器捕獲。

@Service
public class UserService {
    public User getUserById(Long id) {
        // 模擬數(shù)據(jù)庫查詢(假設(shè)id=100的用戶不存在)
        User user = null; 
        if (user == null) {
            throw new BusinessException(4001, "用戶ID=" + id + "不存在"); // 拋業(yè)務(wù)異常
        }
        return user;
    }
}
@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/{id}")
    public Result<User> getUser(@PathVariable Long id) {
        User user = userService.getUserById(id);
        return Result.success(user); // 正常返回
    }
}

測試結(jié)果:

  • id=100時,返回{"code":4001,"msg":"用戶ID=100不存在","data":null}(業(yè)務(wù)異常被捕獲)。
  • id=1(存在用戶)時,返回{"code":200,"msg":"操作成功","data":{...}}(正常響應(yīng))。

三、進階玩法:這些場景也能輕松搞定!

3.1 自定義HTTP狀態(tài)碼(比如404)

如果想讓某些異常返回特定的HTTP狀態(tài)碼(如“資源不存在”返回404),可以用@ResponseStatus注解。

// 自定義異常(標記為404狀態(tài)碼)
@ResponseStatus(HttpStatus.NOT_FOUND) 
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String msg) {
        super(msg);
    }
}
// 全局處理(可選,也可以直接用@ResponseStatus)
@ExceptionHandler(ResourceNotFoundException.class)
public Result<?> handleResourceNotFound(ResourceNotFoundException e) {
    return Result.error(404, e.getMessage());
}

3.2 處理表單參數(shù)校驗異常(@ModelAttribute)

如果是表單提交(非@RequestBody),參數(shù)校驗失敗會拋BindException,處理方式和MethodArgumentNotValidException類似:

@ExceptionHandler(BindException.class)
public Result<?> handleBindException(BindException e) {
    String errorMsg = e.getBindingResult().getFieldErrors().stream()
            .map(FieldError::getDefaultMessage)
            .collect(Collectors.joining(";"));
    return Result.error(400, "參數(shù)校驗失敗:" + errorMsg);
}

3.3 記錄異常日志的細節(jié)

全局處理中記錄日志時,建議帶上請求路徑、用戶ID(如果有登錄)等信息,方便排查問題:

@ExceptionHandler(Exception.class)
public Result<?> handleSystemException(Exception e) {
    // 獲取請求路徑
    String path = getRequestPath();
    // 獲取用戶ID(假設(shè)從Token中解析)
    String userId = SecurityUtils.getCurrentUserId(); 
    // 記錄日志(包含關(guān)鍵上下文信息)
    log.error("系統(tǒng)異常 | 用戶ID={} | 路徑={} | 異常信息={}", 
              userId, path, e.getMessage(), e); 
    return Result.error(500, "服務(wù)器繁忙,請稍后再試");
}

四、避坑指南:這些坑別踩!

4.1 全局異常不生效?

  • 檢查是否添加了@RestControllerAdvice注解(別漏了@ResponseBody)。
  • 檢查異常類的包路徑是否被Spring掃描到(確保全局處理器和業(yè)務(wù)類在同一個或子包下)。
  • 檢查是否有局部try-catch覆蓋了全局處理(比如Controller里自己catch了異常,沒拋出去)。

4.2 生產(chǎn)環(huán)境暴露敏感信息?

  • 系統(tǒng)異常(如SQLException)的msg不要直接返回給前端,用“服務(wù)器繁忙”代替。
  • 日志中可以記錄完整堆棧,但響應(yīng)體里只保留友好提示。

4.3 自定義異常沒被捕獲?

  • 確保自定義異常是RuntimeException的子類(Spring默認只捕獲RuntimeExceptionError)。
  • 如果是檢查型異常(如IOException),需要在方法上聲明throws,或手動拋RuntimeException包裝。

五、總結(jié):全局異常處理的學(xué)習(xí)路線

  1. 基礎(chǔ)用法:用@RestControllerAdvice+@ExceptionHandler捕獲所有異常,返回統(tǒng)一Result。
  2. 業(yè)務(wù)異常:自定義BusinessException,在Service層拋出,全局處理返回業(yè)務(wù)碼。
  3. 參數(shù)校驗:用@Valid+MethodArgumentNotValidException,提取校驗錯誤信息。
  4. 系統(tǒng)異常:兜底處理Exception,記錄日志并返回友好提示。
  5. 進階優(yōu)化:自定義狀態(tài)碼、記錄請求上下文、處理表單參數(shù)異常。

掌握這些,你的Spring Boot項目異常處理將告別“屎山代碼”,變得簡潔、優(yōu)雅、易維護!趕緊動手試試吧~ 有其他問題歡迎在評論區(qū)留言,我會一一解答! ??

到此這篇關(guān)于Spring Boot全局異常處理保姆級教程從入門到實戰(zhàn)(看完秒懂)的文章就介紹到這了,更多相關(guān)Spring Boot全局異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • ActiveMQ持久化機制代碼實例

    ActiveMQ持久化機制代碼實例

    這篇文章主要介紹了ActiveMQ持久化機制代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • 深入理解Java中的注解Annotation

    深入理解Java中的注解Annotation

    這篇文章主要介紹了深入理解Java中的注解Annotation,注解在Java中確實也很常見,但是人們常常不會自己定義一個注解拿來用,我們雖然很少去自定義注解,但是學(xué)會注解的寫法,注解的定義,學(xué)會利用反射解析注解中的信息,在開發(fā)中能夠使用到,這是很關(guān)鍵的,需要的朋友可以參考下
    2023-10-10
  • SpringBoot導(dǎo)入mail依賴報錯問題解決

    SpringBoot導(dǎo)入mail依賴報錯問題解決

    這篇文章主要介紹了SpringBoot導(dǎo)入mail依賴報錯問題解決,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • springboot配置數(shù)據(jù)庫密碼特殊字符報錯的解決

    springboot配置數(shù)據(jù)庫密碼特殊字符報錯的解決

    這篇文章主要介紹了springboot配置數(shù)據(jù)庫密碼特殊字符報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • SpringBoot整合Log4j2及配置步驟

    SpringBoot整合Log4j2及配置步驟

    這篇文章主要介紹了SpringBoot整合Log4j2以及配置詳解,刪除spring-boot-starter-parent默認使用spring-boot-starter-logging依賴,本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • Java使用junit框架進行代碼測試過程詳解

    Java使用junit框架進行代碼測試過程詳解

    單元測試就是針對最小的功能單元編寫測試代碼,Junit是使用Java語言實現(xiàn)的單元測試框架,它是開源的,Java開發(fā)者都應(yīng)當學(xué)習(xí)并使用Junit編寫單元測試。本文就來講講Junit框架的使用教程,需要的可以參考一下
    2023-02-02
  • 詳解Javascript判斷Crontab表達式是否合法

    詳解Javascript判斷Crontab表達式是否合法

    這篇文章主要介紹了詳解Javascript判斷Crontab表達式是否合法的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Java利用Redis實現(xiàn)高并發(fā)計數(shù)器的示例代碼

    Java利用Redis實現(xiàn)高并發(fā)計數(shù)器的示例代碼

    這篇文章主要介紹了Java利用Redis實現(xiàn)高并發(fā)計數(shù)器的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • 簡單了解spring cloud 網(wǎng)關(guān)服務(wù)

    簡單了解spring cloud 網(wǎng)關(guān)服務(wù)

    這篇文章主要介紹了簡單了解spring cloud 網(wǎng)關(guān)服務(wù),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • 使用mybatis的typeHandler對clob進行流讀寫方式

    使用mybatis的typeHandler對clob進行流讀寫方式

    這篇文章主要介紹了使用mybatis的typeHandler對clob進行流讀寫方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01

最新評論

吴忠市| 虎林市| 蒙自县| 紫阳县| 陆河县| 嘉定区| 平江县| 安西县| 乌兰察布市| 阳江市| 松滋市| 邻水| 增城市| 加查县| 罗城| 巴彦县| 瓦房店市| 木兰县| 潞城市| 洪泽县| 高邑县| 抚松县| 手游| 秀山| 乐昌市| 读书| 江永县| 合肥市| 肥乡县| 宜都市| 庆阳市| 桦川县| 麻江县| 桦南县| 定陶县| 互助| 太原市| 丹巴县| 阳曲县| 临沭县| 桓仁|