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

SpringBoot配置全局異常處理器捕獲異常詳解

 更新時間:2023年04月03日 10:27:23   作者:啊哈ㄚ  
spring-boot統(tǒng)一異常捕獲,異常時相對于return的一種退出機制,可以由系統(tǒng)觸發(fā),下面這篇文章主要給大家介紹了關于SpringBoot配置全局異常處理器捕獲異常的相關資料,需要的朋友可以參考下

1.前言

任何系統(tǒng),我們不會傻傻的在每一個地方進行異常捕獲和處理,整個系統(tǒng)一般我們會在一個的地方統(tǒng)一進行異常處理,spring boot全局異常處理很簡單;

前后端分離,后端API,一般對于異常處理,要做得無非兩件事,

1.是記錄日志及相應通知處理,這是對內(nèi)的,

2.是給出返回結(jié)果給API調(diào)用者,這是對外的;

對API調(diào)用者來說,他只需要一個返回結(jié)果(包含錯誤代碼、提示信息),其他的他不關心

對后端來說,他只需要記錄日志,通知或者給發(fā)布相應消息給其他隊列處理相關事項;

所以:看到過不少人封裝了很多個自定義異常類,其實,完全沒有必要,只需要一個異常處理來處理所有異常即可,然后封裝一個錯誤識別碼和提示消息的枚舉,用于返回給API調(diào)用者;然后后端的處理,直接在一個異常處理方法中全部處理就行了,完全沒必要封裝N多個自定義異常,那沒有任何意義;

關于異常的思想認識

我們應該認識到,一切異常,對系統(tǒng)來說,都是不正常的表現(xiàn),都是屬于缺陷,都屬于BUG,盡管有些異常是我們主動拋出的;

我們要做的,是應該盡量提高系統(tǒng)可用性,最大限度避免任何異常的出現(xiàn),而不是去指望完善異常處理來完善系統(tǒng);

異常處理,是異常無法避免的出現(xiàn)了而采取的一種應急措施,主要目的是對外增加友好性,對內(nèi)提供補救線索;

不要認為完善的異常處理是系統(tǒng)核心,他不是,不要指望異常處理盡善盡美,不要指望異常處理來給系統(tǒng)缺陷擦屁股;

如果系統(tǒng)異常過多,那么你要做的不是去完善異常處理機制,而是要好好去反思:系統(tǒng)架構(gòu)設計是否合理,系統(tǒng)邏輯設計是否合理;

2.全局異常并處理的方法一(@ControllerAdvice 和 @ExceptionHandler)

=================================================

在開發(fā)中,我們會有如下的場景:某個接口中,存在一些業(yè)務異常。例如用戶輸入的參數(shù)校驗失敗、用戶名密碼不存在等。當觸發(fā)這些業(yè)務異常時,我們需要拋出這些自定義的業(yè)務異常,并對其進行處理。一般我們要把這些異常信息的狀態(tài)碼和異常描述,友好地返回給調(diào)用者,調(diào)用者則利用狀態(tài)碼等信息判斷異常的具體情況。

過去,我們可能需要在 controller 層通過 try/catch 處理。首先 catch 自定義異常,然后 catch 其它異常。對于不同的異常,我們需要在 catch 的同時封裝將要返回的對象。然而,這么做的弊端就是代碼會變得冗長。每個接口都需要做 try/catch 處理,而且一旦需要調(diào)整,所有的接口都需要修改一遍,非常不利于代碼的維護,如下段代碼所示

@RequestMapping (value = "/test")
public ResponseEntity test() {
    ResponseEntity re = new ResponseEntity();
    // 業(yè)務處理
    // ...
    try {
        // 業(yè)務
    } catch (BusinessException e) {
        logger.info("業(yè)務發(fā)生異常,code:" + e.getCode() + "msg:" + e.getMsg());
        re.setCode(e.getCode());
        re.setMsg(e.getMsg());
        return re;
    } catch (Exception e) {
        logger.error("服務錯誤:", e);
        re.setCode("xxxxx");
        re.setMsg("服務錯誤");
        return re;
    }
    return re;
}

那么,有沒有什么方法可以簡便地處理這些異常信息呢?答案是肯定的。Spring 3.2 中,新增了 @ControllerAdvice 注解,可以用于定義 @ExceptionHandler 、 @InitBinder 、@ModelAttribute ,并應用到所有 @RequestMapping 中。簡單來說就是,可以通過@ControllerAdvice 注解配置一個全局異常處理類,來統(tǒng)一處理 controller 層中的異常,于此同時 controller 中可以不用再寫 try/catch,這使得代碼既整潔又便于維護。

使用方法

定義自定義異常

有關自定義異常相關知識點這里就不詳細說明了,如果不了解的話自行搜索一下。這里貼上一個簡單的自定義業(yè)務異常類。

/**
 * 自定義業(yè)務異常類
 *
 * @author Yuzhe Ma
 * @date 2018/11/28
 */
@Data
public class BusinessException extends RuntimeException {
    private String code;
    private String msg;
 
    public BusinessException(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}

注: @Data 為 Lombok 插件。自動生成 set/get 方法。具體使用方法這里就不展開介紹了。

@ControllerAdvice + @ExceptionHand` 配置全局異常處理類

/**
 * 全局異常處理器
 *
 * @author Yuzhe Ma
 * @date 2018/11/12
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
 
    /**
     * 處理 Exception 異常
     *
     * @param httpServletRequest httpServletRequest
     * @param e                  異常
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public ResponseEntity exceptionHandler(HttpServletRequest httpServletRequest, Exception e) {
        logger.error("服務錯誤:", e);
        return new ResponseEntity("xxx", "服務出錯");
    }
 
    /**
     * 處理 BusinessException 異常
     *
     * @param httpServletRequest httpServletRequest
     * @param e                  異常
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = BusinessException.class)
    public ResponseEntity businessExceptionHandler(HttpServletRequest httpServletRequest, BusinessException e) {
        logger.info("業(yè)務異常。code:" + e.getCode() + "msg:" + e.getMsg());
        return new ResponseEntity(e.getCode(), e.getMsg());
    }
}

@ControllerAdvice

定義該類為全局異常處理類。

@ExceptionHandler

定義該方法為異常處理方法。value 的值為需要處理的異常類的 class 文件。在例子中,方法傳入兩個參數(shù)。一個是對應的 Exception 異常類,一個是 HttpServletRequest 類。當然,除了這兩種參數(shù),還支持傳入一些其他參數(shù)。詳見文檔 https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html

這樣,就可以對不同的異常進行統(tǒng)一處理了。通常,為了使 controller 中不再使用任何 try/catch,也可以在 GlobalExceptionHandler 中對 Exception 做統(tǒng)一處理。這樣其他沒有用 @ExceptionHandler 配置的異常就都會統(tǒng)一被處理。

遇到異常時拋出異常即可

在業(yè)務中,遇到業(yè)務異常的地方,直接使用 throw 拋出對應的業(yè)務異常即可。例如

throw new BusinessException("3000", "賬戶密碼錯誤");

在 Controller 中的寫法

Controller 中,不需要再寫 try/catch,除非特殊用途。

@RequestMapping(value = "/test")
public ResponseEntity test() {
    ResponseEntity re = new ResponseEntity();
    // 業(yè)務處理
    // ...
    return re;
}

結(jié)果展示

異常拋出后,返回如下結(jié)果。

{
    "code": "3000",
    "msg": "賬戶密碼錯誤",
    "data": null
}

注意 不一定必須在 controller 層本身拋出異常才能被 GlobalExceptionHandler 處理,只要異常最后是從 contoller 層拋出去的就可以被全局異常處理器處理。異步方法中的異常不會被全局異常處理。拋出的異常如果被代碼內(nèi)的 try/catch 捕獲了,就不會被 GlobalExceptionHandler 處理了。總結(jié)

本文介紹了在 SpringBoot 中,通過配置全局異常處理器統(tǒng)一處理 Controller 層引發(fā)的異常。

優(yōu)點

減少代碼冗余,代碼便于維護

缺點

只能處理 controller 層拋出的異常,對例如 Interceptor(攔截器)層的異常、定時任務中的異常、異步方法中的異常,不會進行處理。

以上就是用 @ControllerAdvice + @ExceptionHand 實現(xiàn) SpringBoot 中捕獲 controller 層全局異常并處理的方法。

3.全局異常并處理的方法二 (AOP)

雖然@ControllerAdvice注解通常和@ExceptionHandler注解用于全局異常的處理。

但是這種方式有個缺點就是,只是對控制層進行了異常攔截,比如像工具類中或者其他類中的異常,并不會攔截。

由于業(yè)務執(zhí)行時不能保證程序不出錯,所以寫代碼必須添加try-catch,但是如果頻繁的添加try-catch則必然導致代碼結(jié)構(gòu)混亂.所以需要進行優(yōu)化.

原則:如果出現(xiàn)了問題一般將檢查異常,轉(zhuǎn)化為運行時異常.

核心原理: 代理動態(tài)思想------->AOP操作

采用自定義AOP的方式可以實現(xiàn)攔截。

有幾個關鍵點

  1. 定義切入點為最大項目包
  2. 采用AOP的@AfterThrowing注解獲取到全局異常捕獲一個例子package com.example.promethuesdemo.exception; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * @author chenzhen * Created by chenzhen on 2020/7/20.
*/
    @Aspect
    @Slf4j
    @Component
    public class GlobalExceptionAspect {
        @Pointcut("execution(* com.example..*.*(..))")
        public void pointcut(){
 
        }
 
        @AfterThrowing(pointcut = "pointcut()",throwing = "e")
        public void afterThrowing(JoinPoint joinPoint,Throwable e){
            log.error("全局捕獲到異常了..............");
            //紀錄錯誤信息
            log.error("系統(tǒng)錯誤:{}", e.getMessage());
            // todo 想要執(zhí)行的操作
        }
 
    }

aop中相關概念

Aspect(切面): Aspect 聲明類似于 Java 中的類聲明,在 Aspect 中會包含著一些 Pointcut 以及相應的 Advice。* Joint point(連接點):表示在程序中明確定義的點,典型的包括方法調(diào)用,對類成員的訪問以及異常處理程序塊的執(zhí)行等等,它自身還可以嵌套其它

joint point。* Pointcut(切點):表示一組 joint point,這些 joint point 或是通過邏輯關系組合起來,或是通過通配、正則表達式等方式集中起來,它定義了相應的 Advice 將要發(fā)生的地方。* Advice(增強):Advice 定義了在 Pointcut 里面定義的程序點具體要做的操作,它通過 before、after 和 around 來區(qū)別是在每個 joint point 之前、之后還是代替執(zhí)行的代碼。* Target(目標對象):織入 Advice 的目標對象.。 Weaving(織入):將 Aspect 和其他對象連接起來, 并創(chuàng)建 Adviced object 的過程

Advice(增強)的類型

before advice, 在 join point 前被執(zhí)行的 advice. 雖然 before advice 是在 join point 前被執(zhí)行, 但是它并不能夠阻止 join point 的執(zhí)行, 除非發(fā)生了異常(即我們在 before advice 代碼中,不能人為地決定是否繼續(xù)執(zhí)行 join point 中的代碼)* after return advice, 在一個 join point 正常返回后執(zhí)行的 advice* after throwing advice, 當一個 join point 拋出異常后執(zhí)行的 advice* after(final) advice, 無論一個 join point 是正常退出還是發(fā)生了異常, 都會被執(zhí)行的 advice.* around advice, 在 join point 前和 joint point 退出后都執(zhí)行的 advice. 這個是最常用的 advice.* introduction,introduction可以為原有的對象增加新的屬性和方法。

注意

spring AOP中的AfterThrowing增強處理可以對目標方法的異常進行處理,但這種處理與直接使用catch捕捉處理異常的方式不同,catch捕捉意味著能完全處理異常,即只要catch塊本身不拋出新的異常,則被處理的異常不會往上級調(diào)用者進一步傳播下去;但是如果使用了AfterThrowing增強處理用于對異常進行處理,處理后異常仍然會往上一級調(diào)用者傳播,如果是在main中調(diào)用的目標方法,那么異常會直接傳到JVM,如下截圖所示:

SpringBoot 之配置全局異常處理器捕獲異常

另外需要注意, 如果目標方法中出現(xiàn)異常,并由catch捕捉處理且catch又沒有拋出新的異常,那么針對該目標方法的AfterThrowing增強處理將不會被執(zhí)行。

總結(jié)

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

相關文章

  • Mybatis使用typeHandler加密的實現(xiàn)

    Mybatis使用typeHandler加密的實現(xiàn)

    本文詳細介紹了如何在Mybatis中使用typeHandler對特定字段進行加密處理,涵蓋了從引入依賴、配置Mybatis,到實現(xiàn)typeHandler繼承類和配置mapper層的詳細步驟,為需要在項目中實現(xiàn)字段加密的開發(fā)者提供了參考和借鑒
    2024-09-09
  • 在SpringBoot中如何利用Redis實現(xiàn)互斥鎖

    在SpringBoot中如何利用Redis實現(xiàn)互斥鎖

    當我們利用Redis存儲熱點數(shù)據(jù)時,突然就過期失效或者被刪除了,導致大量請求同時訪問數(shù)據(jù)庫,增加了數(shù)據(jù)庫的負載,為減輕數(shù)據(jù)庫的負載我們利用互斥鎖,本文重點介紹在SpringBoot中如何利用Redis實現(xiàn)互斥鎖,感興趣的朋友一起看看吧
    2023-09-09
  • Java異常分類處理拋出捕獲操作詳解

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

    異常就是不正常,比如當我們身體出現(xiàn)了異常我們會根據(jù)身體情況選擇喝開水、吃藥、看病、等 異常處理方法。 java異常處理機制是我們java語言使用異常處理機制為程序提供了錯誤處理的能力,程序出現(xiàn)的錯誤,程序可以安全的退出,以保證程序正常的運行等
    2022-09-09
  • Java日常練習題,每天進步一點點(37)

    Java日常練習題,每天進步一點點(37)

    下面小編就為大家?guī)硪黄狫ava基礎的幾道練習題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-07-07
  • Java中你真的會用Constructor構(gòu)造器嗎之看完本篇你就真的會了

    Java中你真的會用Constructor構(gòu)造器嗎之看完本篇你就真的會了

    顯式初始化要求我們在寫程序時就確定初始值,這有時很不方便。我們可以使用構(gòu)造器(constructor)來初始化對象。構(gòu)造器可以初始化數(shù)據(jù)成員,還可以規(guī)定特定的操作。這些操作會在創(chuàng)建對象時自動執(zhí)行。下面文字將對該內(nèi)容做詳細介紹,需要的小伙伴請參考
    2021-09-09
  • Java枚舉類型與泛型使用解讀

    Java枚舉類型與泛型使用解讀

    這篇文章主要介紹了Java枚舉類型與泛型使用解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • SpringBoot中的@PostConstruct注解詳細解析

    SpringBoot中的@PostConstruct注解詳細解析

    這篇文章主要介紹了SpringBoot中的@PostConstruct注解詳細解析,@PostConstruct注解,主要用于在Spring容器啟動時執(zhí)行某些操作或者任務,@PostConstruct注解一般放在BEAN的方法上,一旦BEAN初始化完成之后,將會調(diào)用這個方法,需要的朋友可以參考下
    2024-01-01
  • Java雪花算法的實現(xiàn)詳解

    Java雪花算法的實現(xiàn)詳解

    雪花算法(Snowflake)是一種分布式唯一ID生成算法,用于生成全局唯一的ID,使用雪花算法生成的ID通常是一個64位的整數(shù),可以根據(jù)需要進行轉(zhuǎn)換和展示,在Java等編程語言中,可以使用相應的庫或工具來生成雪花算法的ID,本文給大家介紹了Java雪花算法的實現(xiàn)
    2023-11-11
  • Spring?MVC內(nèi)置過濾器功能示例詳解

    Spring?MVC內(nèi)置過濾器功能示例詳解

    這篇文章主要為大家介紹了Spring?MVC內(nèi)置過濾器使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • Java實現(xiàn)lucene搜索功能的方法(推薦)

    Java實現(xiàn)lucene搜索功能的方法(推薦)

    下面小編就為大家?guī)硪黄狫ava實現(xiàn)lucene搜索功能的方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12

最新評論

西昌市| 冀州市| 南充市| 铜川市| 霍林郭勒市| 东乌珠穆沁旗| 光泽县| 奉新县| 中牟县| 大洼县| 迁西县| 巩义市| 库伦旗| 昭通市| 霍邱县| 丹寨县| 丹寨县| 伊金霍洛旗| 贞丰县| 神池县| 保靖县| 安塞县| 交城县| 柘荣县| 铜梁县| 通州区| 扎兰屯市| 隆安县| 巨鹿县| 德化县| 中山市| 黔江区| 宜川县| 霍城县| 安平县| 吉林省| 永胜县| 宝鸡市| 墨竹工卡县| 游戏| 藁城市|