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

@ControllerAdvice之全局異常處理過程

 更新時間:2025年11月05日 09:37:46   作者:Tech_Jia_Hui  
文章介紹了在Java中處理異常的兩種方式:就地解決和向上拋出,并重點(diǎn)介紹了Spring框架中的@ControllerAdvice注解,用于實(shí)現(xiàn)全局異常處理,從而避免了在每個Controller類中重復(fù)編寫try-catch代碼塊,這種方法不僅提高了代碼的可維護(hù)性,還使得異常處理邏輯的修改更加方便

背景

在業(yè)務(wù)邏輯中存在大量重復(fù)的 try-catch 代碼塊(且沒有全局異常處理機(jī)制)會帶來以下顯著問題:

  • 每個方法都需要手動編寫 try-catch,導(dǎo)致大量重復(fù)代碼,違反 DRY(Don’t Repeat Yourself)原則。
  • 如果異常處理邏輯需要調(diào)整(例如日志格式、錯誤碼規(guī)范),必須逐個修改所有 try-catch 塊,容易遺漏或出錯。
public void processOrder() {
    try {
        // 業(yè)務(wù)邏輯
    } catch (OrderException e) {
        log.error("訂單處理失敗: {}", e.getMessage());
    }
}

public void refundOrder() {
    try {
        // 業(yè)務(wù)邏輯
    } catch (RefundException e) {
        log.error("退款失敗: {}", e.getMessage());
    }
}

java中的異常處理方式

1、就地解決

即用try-catch塊包裹住容易發(fā)生異常的代碼片段,這樣當(dāng)該代碼片段真正發(fā)生異常后,就會立即被catch塊捕捉并在catch塊中處理,從而使代碼繼續(xù)往下執(zhí)行,不影響其他代碼的執(zhí)行。

2、向上拋出

如果不想立馬就地處理,可以選擇將該異常向上拋出,讓方法的調(diào)用者處理。若方法的調(diào)用者也不行處理,同樣可以繼續(xù)向上拋出該異常,以此類推,直到將該異常拋給JVM處理??墒荍VM懶啊,一看你們該處理的都不處理是吧,好,我也不處理,我還要把你們方法的調(diào)用過程給曬出來,結(jié)果就可以在控制臺看到方法調(diào)用的堆棧信息了。

為什么要使用全局異常處理

總是用try-catch塊包裹代碼塊也不好,影響性能不說代碼看著不是很美觀,所以我們選擇用第二種——向上拋出的方式。向上拋出沒問題,但總要有一個地方處理該異常,在web系統(tǒng)當(dāng)中還應(yīng)該將該異常以一個用戶可以接受的方式返回給前端,不但在接口對接的時候讓前端小姐姐知道是我們后臺接口出現(xiàn)了問題,不至于摸不著頭腦;而且我們后端開發(fā)人員也能根據(jù)接口返回的結(jié)果快速的知道到底是哪里出現(xiàn)了問題,才能快速解決問題。

全局異常處理

Spring在3.2版本增加了一個注解@ControllerAdvice,可以與@ExceptionHandler、@InitBinder、@ModelAttribute 等注解注解配套使用。

不過跟異常處理相關(guān)的只有注解@ExceptionHandler(該注解是springmvc中的一個注解)

該注解的作用:它通常用在控制器(Controller)類的方法上,以指定該方法用于處理特定類型的異常。當(dāng)控制器中的其他方法拋出該異常時,Spring 會自動調(diào)用帶有 @ExceptionHandler 注解的方法來處理該異常。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

// 這是一個簡單的控制器類
@RestController
public class MyController {

    // 一個可能會拋出異常的方法
    public String doSomething() {
        // 假設(shè)這里有一些邏輯,可能會拋出 IllegalArgumentException
        if (true) { // 這里只是為了演示,實(shí)際上應(yīng)該有具體的邏輯判斷
            throw new IllegalArgumentException("Invalid argument provided");
        }
        return "Success";
    }

    // 使用 @ExceptionHandler 來處理 IllegalArgumentException
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException ex) {
        // 創(chuàng)建一個包含錯誤信息的響應(yīng)實(shí)體
        return new ResponseEntity<>("Invalid argument: " + ex.getMessage(), HttpStatus.BAD_REQUEST);
    }
}
在上面的例子中,doSomething 方法可能會拋出一個 IllegalArgumentException。當(dāng)這個異常被拋出時,Spring 會自動調(diào)用 handleIllegalArgumentException 方法來處理它,并返回一個包含錯誤信息的 ResponseEntity 對象,其 HTTP 狀態(tài)碼為 400 Bad Request。

但是,這樣一來,就必須在每一個Controller類都定義一套這樣的異常處理方法,因?yàn)楫惓?梢允歉鞣N各樣。這樣一來,就會造成大量的冗余代碼,而且若需要新增一種異常的處理邏輯,就必須修改所有Controller類了,很不優(yōu)雅。

當(dāng)然你可能會說,那就定義個類似BaseController的基類,這樣總行了吧。

這種做法雖然沒錯,但仍不盡善盡美,因?yàn)檫@樣的代碼有一定的侵入性和耦合性。簡簡單單的Controller,我為啥非得繼承這樣一個類呢,萬一已經(jīng)繼承其他基類了呢。大家都知道Java只能繼承一個類。

那有沒有一種方案,既不需要跟Controller耦合,也可以將定義的 異常處理器 應(yīng)用到所有控制器呢?所以注解@ControllerAdvice出現(xiàn)了,簡單的說,該注解可以把異常處理器應(yīng)用到所有控制器,而不是單個控制器。借助該注解,我們可以實(shí)現(xiàn):在獨(dú)立的某個地方,比如單獨(dú)一個類,定義一套對各種異常的處理機(jī)制,然后在類的簽名加上注解@ControllerAdvice,統(tǒng)一對 不同階段的、不同異常 進(jìn)行處理。這就是統(tǒng)一異常處理的原理。

@ControllerAdvice使用

1、創(chuàng)建 MyControllerAdvice.java

如下:

package com.sam.demo.controller;

import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

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

/**
 * controller 增強(qiáng)器
 *
 * @author sam
 * @since 2017/7/17
 */
@ControllerAdvice
public class MyControllerAdvice {

    /**
     * 全局異常捕捉處理
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Map errorHandler(Exception ex) {
        Map map = new HashMap();
        map.put("code", 100);
        map.put("msg", ex.getMessage());
        return map;
    }
    
    /**
     * 攔截捕捉自定義異常 MyException.class
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = MyException.class)
    public Map myErrorHandler(MyException ex) {
        Map map = new HashMap();
        map.put("code", ex.getCode());
        map.put("msg", ex.getMsg());
        return map;
    }

}

2、controller中拋出異常進(jìn)行測試

@RequestMapping("/home")
public String home() throws Exception {

//        throw new Exception("Sam 錯誤");
    throw new MyException("101", "Sam 錯誤");

}

啟動應(yīng)用,訪問:http://localhost:8080/home ,正常顯示以下json內(nèi)容,證明自定義異常已經(jīng)成功被攔截。

{"msg":"Sam 錯誤","code":"101"}

@ControllerAdvice的原理

1、組件掃描與注冊

  • 注解標(biāo)記:當(dāng)類被 @ControllerAdvice 標(biāo)注時,Spring 會在啟動時通過組件掃描(Component Scan)發(fā)現(xiàn)該類。
  • Bean 注冊:將該類注冊為特殊的全局組件,其優(yōu)先級高于普通 Controller,但低于具體的 Controller 方法。

2、異常處理流程

當(dāng) Controller 方法拋出異常時,Spring MVC 的處理流程如下:

  • 異常拋出:Controller 方法執(zhí)行中拋出異常(如 throw new ServiceException())。
  • 異常傳播:異常被 Spring 的 DispatcherServlet 捕獲。
  • 查找處理器:Spring 遍歷所有 @ControllerAdvice 類中的 @ExceptionHandler 方法,尋找與異常類型匹配的方法。
    執(zhí)行處理:調(diào)用匹配的 @ExceptionHandler 方法生成響應(yīng)(如返回 JSON 錯誤信息)。
  • 返回響應(yīng):將處理結(jié)果返回客戶端,中斷原始請求流程。
@ControllerAdvice
public class GlobalExceptionHandler {

    // 處理特定異常
    @ExceptionHandler(ServiceException.class)
    @ResponseBody
    public ResponseResult<Void> handleServiceException(ServiceException e) {
        return ResponseResult.fail(e.getCode(), e.getMessage());
    }

    // 處理所有未捕獲的異常
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseResult<Void> handleException(Exception e) {
        return ResponseResult.fail(500, "系統(tǒng)繁忙");
    }
}

3、優(yōu)先級規(guī)則

  • 精確匹配優(yōu)先:@ExceptionHandler 方法定義的異常類型越具體,優(yōu)先級越高。
  • Controller 內(nèi)優(yōu)先:若 Controller 內(nèi)部定義了 @ExceptionHandler,則優(yōu)先于全局 @ControllerAdvice。
  • 多個 @ControllerAdvice 類:通過 @Order 注解指定優(yōu)先級,數(shù)值越小優(yōu)先級越高。

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解Spring AOP 攔截器的基本實(shí)現(xiàn)

    詳解Spring AOP 攔截器的基本實(shí)現(xiàn)

    本篇文章主要介紹了詳解Spring AOP 攔截器的基本實(shí)現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • Java 中的CharArrayReader 介紹_動力節(jié)點(diǎn)Java學(xué)院整理

    Java 中的CharArrayReader 介紹_動力節(jié)點(diǎn)Java學(xué)院整理

    CharArrayReader 是字符數(shù)組輸入流。它和ByteArrayInputStream類似,只不過ByteArrayInputStream是字節(jié)數(shù)組輸入流,而CharArray是字符數(shù)組輸入流。CharArrayReader 是用于讀取字符數(shù)組,它繼承于Reader
    2017-05-05
  • 解決spring-boot-maven-plugin報紅的問題

    解決spring-boot-maven-plugin報紅的問題

    這篇文章主要給大家介紹一下如何解決spring-boot-maven-plugin報紅的問題,文中通過圖文講解的非常詳細(xì),具有一定的參考價值,需要的朋友可以參考下
    2023-08-08
  • 詳解Java中運(yùn)算符及用法

    詳解Java中運(yùn)算符及用法

    這篇文章主要介紹了詳解Java中運(yùn)算符以及相關(guān)的用法講解,一起跟著小編學(xué)習(xí)下吧。
    2017-12-12
  • Java 深入探討設(shè)計(jì)模式之原型模式篇

    Java 深入探討設(shè)計(jì)模式之原型模式篇

    設(shè)計(jì)模式(Design pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性
    2021-10-10
  • Java使用OpenOffice將office文件轉(zhuǎn)換為PDF的示例方法

    Java使用OpenOffice將office文件轉(zhuǎn)換為PDF的示例方法

    OpenOffice是一個開源的辦公套件,它包含了文檔處理、電子表格、演示文稿以及繪圖等多種功能,類似于Microsoft Office,本文將給大家介紹Java使用OpenOffice將office文件轉(zhuǎn)換為PDF的示例方法,需要的朋友可以參考下
    2024-09-09
  • springboot訪問不存在的URL時的處理方法

    springboot訪問不存在的URL時的處理方法

    在前后端分離的模式下,當(dāng)Spring Boot應(yīng)用接收到一個不存在的URL請求時,通常希望返回一個固定的JSON字符串作為響應(yīng),以便前端能夠據(jù)此進(jìn)行相應(yīng)的處理,本文給大家介紹了springboot訪問不存在的URL時的處理方法,需要的朋友可以參考下
    2024-12-12
  • Java CountDownLatch應(yīng)用場景代碼實(shí)例

    Java CountDownLatch應(yīng)用場景代碼實(shí)例

    這篇文章主要介紹了Java CountDownLatch應(yīng)用場景代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-09-09
  • Springboot如何連接遠(yuǎn)程服務(wù)器上的數(shù)據(jù)庫實(shí)踐

    Springboot如何連接遠(yuǎn)程服務(wù)器上的數(shù)據(jù)庫實(shí)踐

    本文主要介紹了Springboot如何連接遠(yuǎn)程服務(wù)器上的數(shù)據(jù)庫實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • JDK1.6“新“特性Instrumentation之JavaAgent(推薦)

    JDK1.6“新“特性Instrumentation之JavaAgent(推薦)

    這篇文章主要介紹了JDK1.6“新“特性Instrumentation之JavaAgent,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08

最新評論

宿迁市| 洞口县| 乌鲁木齐市| 壶关县| 福泉市| 罗城| 额济纳旗| 雷州市| 安阳市| 宁国市| 潞西市| 乌兰察布市| 洱源县| 大新县| 丹江口市| 胶南市| 绵竹市| 墨竹工卡县| 和顺县| 黑山县| 秦皇岛市| 宣化县| 新宁县| 阿拉善盟| 班玛县| 宜宾市| 庐江县| 嘉峪关市| 措美县| 邛崃市| 娱乐| 岳阳市| 云林县| 犍为县| 和林格尔县| 融水| 新邵县| 察哈| 延寿县| 衡山县| 英德市|