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

Java后端Spring?Boot全局異常處理最佳實(shí)踐記錄

 更新時(shí)間:2025年08月22日 10:10:58   作者:柯南二號(hào)  
Spring Boot通過(guò)和提供強(qiáng)大的異常處理機(jī)制,支持統(tǒng)一REST和頁(yè)面錯(cuò)誤響應(yīng),這篇文章主要介紹了Java后端Spring?Boot全局異常處理的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在日常開(kāi)發(fā)中,異常處理幾乎是繞不過(guò)去的一個(gè)話題。尤其在 后端 API 項(xiàng)目 中,如果沒(méi)有統(tǒng)一的異常處理機(jī)制,很容易出現(xiàn)以下問(wèn)題:

  • Controller 層代碼里充斥著 try-catch,顯得冗余。
  • 前端拿到的錯(cuò)誤響應(yīng)格式不一致,增加解析成本。
  • 系統(tǒng)異常與業(yè)務(wù)異?;祀s,難以追蹤和排查。

因此,在 Spring Boot 項(xiàng)目中,我們通常會(huì)通過(guò) 全局異常處理 來(lái)收斂所有錯(cuò)誤,保證接口返回結(jié)構(gòu)的統(tǒng)一性,并簡(jiǎn)化開(kāi)發(fā)。

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

在沒(méi)有全局異常處理之前,開(kāi)發(fā)者常常這樣寫代碼:

@GetMapping("/{id}")
public User getUser(@PathVariable int id) {
    try {
        return userService.findById(id);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

問(wèn)題在于:

  1. try-catch 邏輯冗余,重復(fù)代碼太多。
  2. 一旦拋出異常,返回值不明確,前端無(wú)法準(zhǔn)確感知錯(cuò)誤信息。

?? 解決方案就是使用 Spring Boot 提供的全局異常處理機(jī)制@ControllerAdvice + @ExceptionHandler。

二、定義統(tǒng)一返回結(jié)果

首先定義一個(gè)通用的響應(yīng)對(duì)象 ApiResponse,用于統(tǒng)一接口返回格式:

public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;

    public ApiResponse(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(200, "success", data);
    }

    public static <T> ApiResponse<T> error(int code, String message) {
        return new ApiResponse<>(code, message, null);
    }

    // getter & setter
}

這樣一來(lái),無(wú)論成功還是失敗,都能保證返回結(jié)果的結(jié)構(gòu)一致。

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

除了系統(tǒng)異常(NullPointerException、SQLException 等),我們還需要定義 業(yè)務(wù)異常,用于明確業(yè)務(wù)邏輯錯(cuò)誤:

public class BusinessException extends RuntimeException {
    private int code;

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

    public int getCode() {
        return code;
    }
}

例如:用戶不存在、余額不足、參數(shù)非法等,都可以通過(guò) BusinessException 來(lái)拋出。

四、編寫全局異常處理器

接下來(lái),通過(guò) @RestControllerAdvice 來(lái)統(tǒng)一捕獲異常:

@RestControllerAdvice
public class GlobalExceptionHandler {

    // 處理業(yè)務(wù)異常
    @ExceptionHandler(BusinessException.class)
    public ApiResponse<?> handleBusinessException(BusinessException ex) {
        return ApiResponse.error(ex.getCode(), ex.getMessage());
    }

    // 處理參數(shù)校驗(yàn)異常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ApiResponse<?> handleValidException(MethodArgumentNotValidException ex) {
        String msg = ex.getBindingResult().getFieldError().getDefaultMessage();
        return ApiResponse.error(400, msg);
    }

    // 兜底異常處理
    @ExceptionHandler(Exception.class)
    public ApiResponse<?> handleException(Exception ex) {
        ex.printStackTrace(); // 可接入日志系統(tǒng)
        return ApiResponse.error(500, "服務(wù)器內(nèi)部錯(cuò)誤");
    }
}

這樣,不管是業(yè)務(wù)異常還是系統(tǒng)異常,都會(huì)走到全局處理器,保證返回結(jié)果的統(tǒng)一性。

五、使用示例

Controller

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/{id}")
    public ApiResponse<String> getUser(@PathVariable int id) {
        if (id == 0) {
            throw new BusinessException(404, "用戶不存在");
        }
        return ApiResponse.success("用戶ID: " + id);
    }
}

請(qǐng)求與響應(yīng)

  • 正常請(qǐng)求:
{
  "code": 200,
  "message": "success",
  "data": "用戶ID: 1"
}
  • 業(yè)務(wù)異常:
{
  "code": 404,
  "message": "用戶不存在",
  "data": null
}
  • 系統(tǒng)異常:
{
  "code": 500,
  "message": "服務(wù)器內(nèi)部錯(cuò)誤",
  "data": null
}

六、總結(jié)

通過(guò) 全局異常處理,我們實(shí)現(xiàn)了以下目標(biāo):

  1. 統(tǒng)一返回結(jié)構(gòu),方便前端解析。
  2. 集中管理異常,減少冗余 try-catch。
  3. 區(qū)分業(yè)務(wù)異常與系統(tǒng)異常,提升代碼可維護(hù)性。
  4. 可擴(kuò)展性強(qiáng),后續(xù)可以接入日志系統(tǒng)(如 Logback、ELK)或異常監(jiān)控平臺(tái)(如 Sentry)。

建議在實(shí)際項(xiàng)目中,將 全局異常處理 作為基礎(chǔ)框架的一部分,避免每個(gè) Controller 重復(fù)造輪子。

七、日志落庫(kù) / ELK 接入最佳實(shí)踐

在真實(shí)的生產(chǎn)環(huán)境中,僅僅返回統(tǒng)一的錯(cuò)誤信息還不夠。我們還需要對(duì)異常進(jìn)行持久化存儲(chǔ)與分析,以便后續(xù)排查問(wèn)題和改進(jìn)系統(tǒng)。

常見(jiàn)的做法有兩種:

1. 日志落庫(kù)(數(shù)據(jù)庫(kù)存儲(chǔ))

在全局異常處理器中,可以將異常信息寫入數(shù)據(jù)庫(kù)(例如 MySQL、PostgreSQL):

@ExceptionHandler(Exception.class)
public ApiResponse<?> handleException(Exception ex, HttpServletRequest request) {
    // 記錄日志信息
    ErrorLog log = new ErrorLog();
    log.setUri(request.getRequestURI());
    log.setMethod(request.getMethod());
    log.setMessage(ex.getMessage());
    log.setStackTrace(Arrays.toString(ex.getStackTrace()));
    log.setCreateTime(LocalDateTime.now());

    errorLogRepository.save(log); // JPA 或 MyBatis 保存

    return ApiResponse.error(500, "服務(wù)器內(nèi)部錯(cuò)誤");
}

其中 ErrorLog 可以定義為:

@Entity
public class ErrorLog {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String uri;
    private String method;
    private String message;
    private String stackTrace;
    private LocalDateTime createTime;

    // getter & setter
}

這樣就能將異常詳細(xì)信息落到數(shù)據(jù)庫(kù),方便后續(xù)查詢與統(tǒng)計(jì)。

2. 接入 ELK(Elasticsearch + Logstash + Kibana)

如果系統(tǒng)日志量較大,推薦接入 ELK,實(shí)現(xiàn)實(shí)時(shí)日志收集與可視化。

(1)配置 Logback 輸出 JSON 日志

logback-spring.xml 中使用 logstash-logback-encoder 輸出 JSON:

<configuration>
    <appender name="LOGSTASH" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/app-log.json</file>
        <encoder class="net.logstash.logback.encoder.LoggingEventEncoder"/>
    </appender>

    <root level="INFO">
        <appender-ref ref="LOGSTASH"/>
    </root>
</configuration>

(2)通過(guò) Logstash 收集日志

配置 Logstash(logstash.conf):

input {
  file {
    path => "/usr/local/app/logs/app-log.json"
    codec => json
  }
}

output {
  elasticsearch {
    hosts => ["http://localhost:9200"]
    index => "springboot-error-%{+YYYY.MM.dd}"
  }
}

(3)在 Kibana 可視化

通過(guò) Kibana Dashboard,可以實(shí)現(xiàn):

  • 錯(cuò)誤趨勢(shì)圖
  • 按 API 維度統(tǒng)計(jì)異常數(shù)量
  • 按時(shí)間維度分析錯(cuò)誤高峰
  • 搜索具體異常堆棧

3. 最佳實(shí)踐建議

  • 開(kāi)發(fā)環(huán)境:控制臺(tái)打印異常即可,方便調(diào)試。
  • 測(cè)試環(huán)境:日志落庫(kù),方便 QA 排查問(wèn)題。
  • 生產(chǎn)環(huán)境:接入 ELK,實(shí)時(shí)收集和可視化,必要時(shí)配合 告警系統(tǒng)(如飛書/釘釘機(jī)器人、Prometheus Alertmanager)

八、飛書機(jī)器人告警接入

在生產(chǎn)環(huán)境中,僅僅記錄日志還不夠。當(dāng)發(fā)生嚴(yán)重異常時(shí),我們希望能 實(shí)時(shí)收到告警通知,避免問(wèn)題被埋沒(méi)。常見(jiàn)的方式就是接入 企業(yè) IM 工具(如飛書、釘釘、企業(yè)微信)。

下面以 飛書自定義機(jī)器人 為例,展示如何在全局異常處理器中推送告警。

1. 創(chuàng)建飛書自定義機(jī)器人

  1. 打開(kāi)飛書群聊 → 設(shè)置 → 群機(jī)器人 → 添加機(jī)器人 → 選擇 自定義機(jī)器人。
  2. 復(fù)制生成的 Webhook 地址,類似:
https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx

2. 編寫工具類(推送異常消息)

使用 RestTemplate 發(fā)送 POST 請(qǐng)求:

@Component
public class FeishuBotNotifier {

    private static final String WEBHOOK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx";

    private final RestTemplate restTemplate = new RestTemplate();

    public void sendAlert(String title, String content) {
        Map<String, Object> body = new HashMap<>();
        body.put("msg_type", "text");
        Map<String, String> text = new HashMap<>();
        text.put("text", String.format("【異常告警】\n標(biāo)題: %s\n詳情: %s", title, content));
        body.put("content", text);

        restTemplate.postForEntity(WEBHOOK_URL, body, String.class);
    }
}

3. 在全局異常處理器中調(diào)用

當(dāng)捕獲到異常時(shí),推送到飛書:

@RestControllerAdvice
@RequiredArgsConstructor
public class GlobalExceptionHandler {

    private final FeishuBotNotifier feishuBotNotifier;

    @ExceptionHandler(Exception.class)
    public ApiResponse<?> handleException(Exception ex, HttpServletRequest request) {
        // 構(gòu)造告警信息
        String title = "SpringBoot 服務(wù)異常";
        String content = String.format("URI: %s\nMethod: %s\n錯(cuò)誤: %s",
                request.getRequestURI(), request.getMethod(), ex.getMessage());

        // 發(fā)送飛書告警
        feishuBotNotifier.sendAlert(title, content);

        ex.printStackTrace();
        return ApiResponse.error(500, "服務(wù)器內(nèi)部錯(cuò)誤");
    }
}

4. 飛書群內(nèi)效果

觸發(fā)異常后,群內(nèi)會(huì)收到類似消息:

【異常告警】
標(biāo)題: SpringBoot 服務(wù)異常
詳情: 
URI: /user/0
Method: GET
錯(cuò)誤: 用戶不存在

九、總結(jié)(終極版 ??)

到這里,我們的 全局異常管理方案 已經(jīng)形成了一整套閉環(huán):

  1. 全局異常處理:統(tǒng)一返回格式,簡(jiǎn)化開(kāi)發(fā)。
  2. 業(yè)務(wù)異常區(qū)分:明確業(yè)務(wù)錯(cuò)誤與系統(tǒng)錯(cuò)誤。
  3. 日志落庫(kù):異??沙志没匪?。
  4. ELK 接入:日志可視化分析,支持查詢與報(bào)表。
  5. 飛書機(jī)器人告警:重大異常實(shí)時(shí)通知,提高運(yùn)維響應(yīng)速度。

?? 這樣一套機(jī)制,基本涵蓋了 從接口開(kāi)發(fā) → 異常收斂 → 日志分析 → 實(shí)時(shí)告警 的完整鏈路,既保證了系統(tǒng)的可維護(hù)性,也提升了線上運(yùn)維的響應(yīng)效率。

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

相關(guān)文章

  • mac系統(tǒng)啟動(dòng)spring項(xiàng)目報(bào)錯(cuò)的問(wèn)題及解決方案

    mac系統(tǒng)啟動(dòng)spring項(xiàng)目報(bào)錯(cuò)的問(wèn)題及解決方案

    這篇文章主要介紹了mac系統(tǒng)啟動(dòng)spring項(xiàng)目報(bào)錯(cuò)的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2026-03-03
  • Java實(shí)現(xiàn)遠(yuǎn)程控制技術(shù)完整源代碼分享

    Java實(shí)現(xiàn)遠(yuǎn)程控制技術(shù)完整源代碼分享

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)遠(yuǎn)程控制技術(shù)完整源代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-08-08
  • 深入了解Java中Cookie和Session的區(qū)別

    深入了解Java中Cookie和Session的區(qū)別

    會(huì)話跟蹤是Web程序中常用的技術(shù),用來(lái)跟蹤用戶的整個(gè)會(huì)話,常用的會(huì)話跟蹤技術(shù)是Cookie與Session,本文就詳細(xì)的介紹一下Java中Cookie和Session的區(qū)別,感興趣的可以了解一下
    2023-06-06
  • SpringBoot啟動(dòng)流程入口參數(shù)創(chuàng)建對(duì)象源碼分析

    SpringBoot啟動(dòng)流程入口參數(shù)創(chuàng)建對(duì)象源碼分析

    這篇文章主要為大家介紹了SpringBoot啟動(dòng)流程入口參數(shù)研究及創(chuàng)建對(duì)象源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • 詳解Spring Boot中初始化資源的幾種方式

    詳解Spring Boot中初始化資源的幾種方式

    這篇文章主要介紹了詳解Spring Boot中初始化資源的幾種方式,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Java異常分類處理拋出捕獲操作詳解

    Java異常分類處理拋出捕獲操作詳解

    異常就是不正常,比如當(dāng)我們身體出現(xiàn)了異常我們會(huì)根據(jù)身體情況選擇喝開(kāi)水、吃藥、看病、等 異常處理方法。 java異常處理機(jī)制是我們java語(yǔ)言使用異常處理機(jī)制為程序提供了錯(cuò)誤處理的能力,程序出現(xiàn)的錯(cuò)誤,程序可以安全的退出,以保證程序正常的運(yùn)行等
    2022-09-09
  • Java如何基于ProcessBuilder類調(diào)用外部程序

    Java如何基于ProcessBuilder類調(diào)用外部程序

    這篇文章主要介紹了Java如何基于ProcessBuilder類調(diào)用外部程序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • 將15位身份證補(bǔ)全為18位身份證的算法示例詳解

    將15位身份證補(bǔ)全為18位身份證的算法示例詳解

    這篇文章主要給大家介紹了關(guān)于將15位身份證補(bǔ)全為18位身份證算法的相關(guān)資料,文中通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編一起來(lái)學(xué)習(xí)學(xué)習(xí)吧。
    2017-06-06
  • 如何在IDEA上安裝scala插件并創(chuàng)建工程(圖文教程)

    如何在IDEA上安裝scala插件并創(chuàng)建工程(圖文教程)

    這篇文章主要介紹了一文教你如何在IDEA上安裝scala插件并創(chuàng)建工程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Java連接ftp服務(wù)器實(shí)例代碼

    Java連接ftp服務(wù)器實(shí)例代碼

    這篇文章主要介紹了Java連接ftp服務(wù)器實(shí)例代碼 的相關(guān)資料,需要的朋友可以參考下
    2015-12-12

最新評(píng)論

法库县| 札达县| 罗定市| 琼结县| 潞西市| 孙吴县| 五台县| 扎囊县| 五河县| 合山市| 蒲江县| 衡阳县| 林甸县| 新津县| 镇江市| 湟源县| 连云港市| 阿拉善左旗| 图片| 中超| 濉溪县| 瓮安县| 上饶县| 尚义县| 静安区| 德保县| 黔西县| 万山特区| 镇江市| 正镶白旗| 马公市| 许昌县| 彭山县| 门源| 牡丹江市| 汉阴县| 房山区| 和田县| 莎车县| 蓝山县| 高安市|