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

Spring?Boot全局異常處理實(shí)戰(zhàn)指南

 更新時間:2025年09月03日 08:46:39   作者:白侖色  
在開發(fā)過程中,異常是不可避免的,Spring?Boot提供了一種簡單而強(qiáng)大的機(jī)制來處理應(yīng)用程序中的異常,即全局異常處理,這篇文章主要介紹了Spring?Boot全局異常處理的相關(guān)資料,需要的朋友可以參考下

引言

在開發(fā) Spring Boot 項(xiàng)目時,你是否遇到過這些問題?

  • ? 不同 Controller 重復(fù)寫 try-catch
  • ? 異常信息格式不統(tǒng)一,前端難以解析
  • ? 系統(tǒng)內(nèi)部錯誤直接暴露給用戶(如堆棧信息)
  • ? 404、500 等狀態(tài)碼處理混亂

這些問題不僅影響用戶體驗(yàn),還可能帶來安全風(fēng)險。

全局異常處理就是 Spring Boot 為我們提供的“統(tǒng)一調(diào)度中心”,它能在異常發(fā)生時自動攔截、處理,并返回友好的響應(yīng)。

本文將帶你從零開始,構(gòu)建一套生產(chǎn)級的全局異常處理機(jī)制,并結(jié)合實(shí)際代碼,讓你徹底掌握這一核心技能。

一、為什么需要全局異常處理?

想象一個電商系統(tǒng):

  • 用戶下單時庫存不足 → 返回“庫存不足,請稍后再試”
  • 訂單ID格式錯誤 → 返回“訂單不存在”
  • 數(shù)據(jù)庫連接失敗 → 記錄日志,返回“系統(tǒng)繁忙,請稍后重試”

如果沒有統(tǒng)一處理,每個接口都要寫類似的 try-catch,代碼重復(fù)且難以維護(hù)。

而有了全局異常處理,就像設(shè)立了一個“客戶服務(wù)中心”,所有異常都由它統(tǒng)一接待、分類處理、禮貌回應(yīng)。

二、核心技術(shù):@ControllerAdvice和@ExceptionHandler

Spring Boot 提供了兩個核心注解來實(shí)現(xiàn)全局異常處理:

注解作用
@ControllerAdvice定義全局異常處理器(可作用于所有 Controller)
@ExceptionHandler指定處理某類異常的方法

三、實(shí)戰(zhàn):構(gòu)建統(tǒng)一異常處理機(jī)制

3.1 定義統(tǒng)一返回格式

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;

    // 成功響應(yīng)
    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(200, "success", data);
    }

    // 失敗響應(yīng)
    public static <T> ApiResponse<T> error(int code, String message) {
        return new ApiResponse<>(code, message, null);
    }
}

3.2 自定義業(yè)務(wù)異常

// 業(yè)務(wù)異?;?
public class BusinessException extends RuntimeException {
    private int code;

    public BusinessException(int code, String message) {
        super(message);
        this.code = code;
    }

    public BusinessException(String message) {
        super(message);
        this.code = 500;
    }

    // getter
    public int getCode() {
        return code;
    }
}

使用示例:

@Service
public class OrderService {
    public void createOrder(Long productId, Integer quantity) {
        if (quantity <= 0) {
            throw new BusinessException(400, "購買數(shù)量必須大于0");
        }
        // ... 其他邏輯
    }
}

3.3 全局異常處理器(核心)

@RestControllerAdvice  // 等價于 @ControllerAdvice + @ResponseBody
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 處理自定義業(yè)務(wù)異常
     */
    @ExceptionHandler(BusinessException.class)
    public ApiResponse<String> handleBusinessException(BusinessException e) {
        log.warn("業(yè)務(wù)異常: {}", e.getMessage());
        return ApiResponse.error(e.getCode(), e.getMessage());
    }

    /**
     * 處理參數(shù)校驗(yàn)異常(@Valid)
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ApiResponse<String> handleValidationException(MethodArgumentNotValidException e) {
        // 獲取第一個錯誤信息
        String errorMessage = e.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(FieldError::getDefaultMessage)
                .findFirst()
                .orElse("參數(shù)校驗(yàn)失敗");
        
        log.warn("參數(shù)校驗(yàn)異常: {}", errorMessage);
        return ApiResponse.error(400, errorMessage);
    }

    /**
     * 處理空指針異常
     */
    @ExceptionHandler(NullPointerException.class)
    public ApiResponse<String> handleNullPointerException(NullPointerException e) {
        log.error("空指針異常", e);
        return ApiResponse.error(500, "系統(tǒng)內(nèi)部錯誤,請聯(lián)系管理員");
    }

    /**
     * 處理所有未被捕獲的異常(兜底)
     */
    @ExceptionHandler(Exception.class)
    public ApiResponse<String> handleException(Exception e) {
        log.error("未處理異常", e);
        return ApiResponse.error(500, "系統(tǒng)繁忙,請稍后重試");
    }

    /**
     * 處理 404 Not Found
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ApiResponse<String> handle404(NoHandlerFoundException e) {
        log.warn("請求路徑不存在: {}", e.getRequestURL());
        return ApiResponse.error(404, "請求的資源不存在");
    }
}

3.4 啟用 404 異常捕獲(重要?。?/h3>

默認(rèn)情況下,404 異常不會進(jìn)入 @ExceptionHandler,需在配置文件中開啟:

# application.yml
spring:
  mvc:
    throw-exception-if-no-handler-found: true  # 找不到處理器時拋出異常

  web:
    resources:
      add-mappings: false  # 關(guān)閉默認(rèn)靜態(tài)資源映射(可選,更嚴(yán)格)

四、測試驗(yàn)證

4.1 創(chuàng)建測試 Controller

@RestController
@RequestMapping("/api")
public class TestController {

    @GetMapping("/business")
    public ApiResponse<String> businessError() {
        throw new BusinessException(400, "用戶名已存在");
    }

    @PostMapping("/validate")
    public ApiResponse<String> validate(@Valid @RequestBody UserForm form) {
        return ApiResponse.success("驗(yàn)證通過");
    }

    @GetMapping("/null")
    public ApiResponse<String> nullPointer() {
        String str = null;
        str.length(); // 觸發(fā) NullPointerException
        return ApiResponse.success("success");
    }

    @GetMapping("/unknown")
    public ApiResponse<String> unknown() {
        throw new RuntimeException("未知錯誤");
    }
}
class UserForm {
    @NotBlank(message = "用戶名不能為空")
    private String username;

    @Min(value = 18, message = "年齡不能小于18歲")
    private Integer age;

    // getter & setter
}

4.2 測試結(jié)果

請求響應(yīng)
GET /api/business{"code":400,"message":"用戶名已存在","data":null}
POST /api/validate(無參數(shù)){"code":400,"message":"用戶名不能為空","data":null}
GET /api/null{"code":500,"message":"系統(tǒng)內(nèi)部錯誤,請聯(lián)系管理員","data":null}
GET /api/unknown{"code":500,"message":"系統(tǒng)繁忙,請稍后重試","data":null}
GET /api/not-exist{"code":404,"message":"請求的資源不存在","data":null}

五、高級技巧與生產(chǎn)實(shí)踐

5.1 異常分類管理

你可以為不同模塊定義不同的異常處理器:

// 用戶模塊異常處理器
@ControllerAdvice("com.example.controller.user")
public class UserExceptionHandler { ... }

// 訂單模塊異常處理器
@ControllerAdvice("com.example.controller.order")
public class OrderExceptionHandler { ... }

5.2 結(jié)合 AOP 記錄異常日志

@Aspect
@Component
public class ExceptionLogAspect {

    @AfterThrowing(pointcut = "@within(org.springframework.web.bind.annotation.RestController)", 
                   throwing = "ex")
    public void logException(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        log.error("方法 {} 發(fā)生異常: {}", methodName, ex.getMessage());
    }
}

5.3 返回錯誤碼枚舉(推薦)

public enum ErrorCode {
    SUCCESS(200, "成功"),
    BAD_REQUEST(400, "請求參數(shù)錯誤"),
    UNAUTHORIZED(401, "未授權(quán)"),
    FORBIDDEN(403, "禁止訪問"),
    NOT_FOUND(404, "資源不存在"),
    SERVER_ERROR(500, "系統(tǒng)內(nèi)部錯誤");

    private final int code;
    private final String message;

    ErrorCode(int code, String message) {
        this.code = code;
        this.message = message;
    }

    // getter
}

使用:

throw new BusinessException(ErrorCode.BAD_REQUEST);

總結(jié):全局異常處理的最佳實(shí)踐

實(shí)踐說明
? 使用 @RestControllerAdvice統(tǒng)一返回 JSON 格式
? 自定義 BusinessException區(qū)分業(yè)務(wù)異常與系統(tǒng)異常
? 記錄日志@Slf4j + log.error/warn
? 敏感信息脫敏不要將數(shù)據(jù)庫錯誤、堆棧信息暴露給前端
? 合理分類異常優(yōu)先處理具體異常,最后是 Exception
? 啟用 404 捕獲配置 throw-exception-if-no-handler-found: true

到此這篇關(guān)于Spring Boot全局異常處理的文章就介紹到這了,更多相關(guān)SpringBoot全局異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot項(xiàng)目上高并發(fā)問題的解決方案

    SpringBoot項(xiàng)目上高并發(fā)問題的解決方案

    本章演示在springboot項(xiàng)目中的高并發(fā)demo,演示導(dǎo)致的問題,以及單機(jī)部署下的解決方案和集群部署下的解決方式以及分布式下的解決方案,文中通過圖文結(jié)合的方式講解的非常詳細(xì),需要的朋友可以參考下
    2024-06-06
  • Java for循環(huán)常見優(yōu)化方法案例詳解

    Java for循環(huán)常見優(yōu)化方法案例詳解

    這篇文章主要介紹了Java for循環(huán)常見優(yōu)化方法案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 基于Java事件監(jiān)聽編寫一個中秋猜燈謎小游戲

    基于Java事件監(jiān)聽編寫一個中秋猜燈謎小游戲

    眾所周知,JavaSwing是Java中關(guān)于窗口開發(fā)的一個工具包,可以開發(fā)一些窗口程序,然后由于工具包的一些限制,導(dǎo)致Java在窗口開發(fā)商并沒有太多優(yōu)勢,不過,在JavaSwing中關(guān)于事件的監(jiān)聽機(jī)制是我們需要重點(diǎn)掌握的內(nèi)容,本文將基于Java事件監(jiān)聽編寫一個中秋猜燈謎小游戲
    2023-09-09
  • 如何用Java Stream寫出既高雅又裝*的代碼

    如何用Java Stream寫出既高雅又裝*的代碼

    如何讓同事看不懂你寫的代碼,然后覺得你非常牛逼,這里用到了stream()與Lambda,需要有點(diǎn)基礎(chǔ),沒基礎(chǔ)你炫個&#128296;優(yōu)雅永不過時~ 看下面文章時記得穿燕尾服,拿高腳杯
    2021-08-08
  • Maven工程pom中如何定義jdk版本

    Maven工程pom中如何定義jdk版本

    這篇文章主要介紹了Maven工程pom中如何定義jdk版本,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java可視化之實(shí)現(xiàn)文本的加密和解密

    Java可視化之實(shí)現(xiàn)文本的加密和解密

    這篇文章主要介紹了Java可視化之實(shí)現(xiàn)文本的加密和解密,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • serialVersionUID作用全面解析

    serialVersionUID作用全面解析

    這篇文章全面解析了java中serialVersionUID的作用,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Java加密算法RSA代碼實(shí)例

    Java加密算法RSA代碼實(shí)例

    這篇文章主要介紹了Java加密算法RSA代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • 計(jì)算兩個字符串最大公有子串

    計(jì)算兩個字符串最大公有子串

    本文主要介紹了計(jì)算兩個字符串最大公有子串的解決方案。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • 深入淺析Random類在高并發(fā)下的缺陷及JUC對其的優(yōu)化

    深入淺析Random類在高并發(fā)下的缺陷及JUC對其的優(yōu)化

    這篇文章主要介紹了Random類在高并發(fā)下的缺陷及JUC對其的優(yōu)化 ,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-04-04

最新評論

江华| 荔波县| 米脂县| 肥乡县| 桑日县| 历史| 沧源| 临桂县| 长宁县| 永和县| 仁化县| 宝清县| 古交市| 景德镇市| 威信县| 桃江县| 台南市| 德惠市| 蓝山县| 沙田区| 鄂伦春自治旗| 马鞍山市| 乃东县| 山丹县| 邳州市| 汾阳市| 河东区| 绩溪县| 桐庐县| 开鲁县| 张北县| 九台市| 永清县| 白朗县| 合川市| 通河县| 金湖县| 理塘县| 安多县| 广宗县| 新安县|