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

基于spring boot實(shí)現(xiàn)一個(gè)全局異常處理器

 更新時(shí)間:2023年09月10日 16:39:54   作者:Java小卷  
在項(xiàng)目開發(fā)中,我們可以基于spring boot提供的切面特性,來很輕松的實(shí)現(xiàn)全局異常的處理,所以本文主要為大家介紹了如何基于spring boot實(shí)現(xiàn)一個(gè)全局異常處理器,有需要的可以參考下

還記得前面我們的實(shí)現(xiàn)邏輯,在service層如果有校驗(yàn)失敗我們會拋出異常,而controller中我們對其并沒有處理,實(shí)際上spring boot有自己全局的錯(cuò)誤處理形式。我們可以基于spring boot提供的切面特性,來很輕松的實(shí)現(xiàn)全局異常的處理,現(xiàn)在我們約定,只要后臺邏輯處理失敗的情況,我們都將拋出異常,包括controller中的處理邏輯。

實(shí)現(xiàn)全局異常處理器

現(xiàn)在我們就來編寫全局異常處理器。

package com.xiaojuan.boot.common.web.support;
import ...
import static com.xiaojuan.boot.common.enums.BusinessError.*;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    /** 維護(hù)一個(gè)錯(cuò)誤碼與http狀態(tài)碼的映射 */
    private Map<Integer, HttpStatus> httpStatusMap;
    @PostConstruct
    private void init() {
        httpStatusMap = new HashMap<>();
        httpStatusMap.put(NO_LOGIN.getValue(), HttpStatus.UNAUTHORIZED);
        httpStatusMap.put(HAS_NO_ROLE.getValue(), HttpStatus.FORBIDDEN);
    }
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<Response<?>> handleException(BusinessException ex) {
        log.error(ex.getMessage(), ex);
        // 默認(rèn)服務(wù)器端錯(cuò)誤,返回500狀態(tài)碼
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        if (!StringUtils.isEmpty(ex.getErrCode()) && httpStatusMap.containsKey(ex.getErrCode())) {
            status = httpStatusMap.get(ex.getErrCode());
        }
        return ResponseEntity.status(status).body(Response.fail(ex.getMessage(), ex.getErrCode(), ex.getData()));
    }
    @ExceptionHandler(Exception.class)
    public ResponseEntity<Response<?>> handleException(Exception ex) {
        log.error(ex.getMessage(), ex);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Response.fail("小卷生鮮電商系統(tǒng)異常:" + ex.getMessage()));
    }
}

代碼詳解

這里我們用了@RestControllerAdvice注解對所有的@RestController修飾的controller都進(jìn)行攔截,只要拋出了異常,就交給這個(gè)處理器來處理。

這里要說下響應(yīng)的http狀態(tài)碼,一般都返回200,某些情況下我們將返回一個(gè)可以讓前端特別處理的狀態(tài)碼,比如用戶未登錄的請求被攔截了我們可以返回401,用戶登錄了卻沒有權(quán)限的操作,我們返回403,這樣前端對這塊直接從http狀態(tài)就能識別請求結(jié)果的狀態(tài)。而對于我們業(yè)務(wù)開發(fā)來說,關(guān)注的是業(yè)務(wù)處理的錯(cuò)誤碼,在這里我們和請求http狀態(tài)碼之間做了一個(gè)映射轉(zhuǎn)換,維護(hù)在httpStatusMap成員變量中。

接下來,我們寫了兩個(gè)異常處理方法,它們都必須用@ExceptionHandler注解來指定我們要處理的異常的類型,這里我們只考慮兩種異常:我們自定義的業(yè)務(wù)異常BusinessException和最大的Exception

對于BusinessException,我們要考慮HttpStatus的判斷邏輯,如果我們將某些業(yè)務(wù)錯(cuò)誤碼和http狀態(tài)碼做了映射,那么對于這些業(yè)務(wù)錯(cuò)誤碼我們就取映射到的http狀態(tài)碼來返回,否則我們返回服務(wù)器端錯(cuò)誤的500狀態(tài)碼。

注意處理方法最后的返回結(jié)果,我們使用的是ResponseEntity<Response<?>>,spring web模塊提供的ResponseEntity可以幫助我們按照指定的http狀態(tài)碼并解析指定格式的內(nèi)容體(Spring Boot默認(rèn)配置json形式)進(jìn)行前端響應(yīng)。而要響應(yīng)的對象就是我們之前定義的Response,只不過我們將字段errCode的類型從原來的String改成了Integer,因?yàn)闃I(yè)務(wù)錯(cuò)誤碼我們就定義為數(shù)值型,同樣的還有BusinessException類中的errCode字段類型的調(diào)整。

除了BusinessException,我們只處理最大的Exception,http狀態(tài)碼固定為500,錯(cuò)誤消息也統(tǒng)一以固定的形式開頭。

錯(cuò)誤碼枚舉類

將應(yīng)用中業(yè)務(wù)錯(cuò)誤碼我們定義在一個(gè)枚舉中進(jìn)行維護(hù):

package com.xiaojuan.boot.common.enums;
import ...
@Getter
@AllArgsConstructor
public enum BusinessError {
    PARAM_INVALID("參數(shù)校驗(yàn)失敗", 10001),
    RECORD_EXISTS("后臺記錄已存在", 10002),
    HAS_NO_ROLE("用戶未授權(quán),不能訪問", 403),
    NO_LOGIN("請先登錄再操作", 401);
    private final String label;
    private final Integer value;
}

這里我們給出默認(rèn)的說明,一般在拋出業(yè)務(wù)異常時(shí)我們可以指定更具體的錯(cuò)誤,而不會使用這里默認(rèn)的錯(cuò)誤消息。

service層拋出異常調(diào)整

現(xiàn)在我們對service層拋出異常做下調(diào)整,一般我們只要傳入錯(cuò)誤信息來構(gòu)造BusinessException。有些時(shí)候我們還可以傳入錯(cuò)誤碼來進(jìn)一步區(qū)分這些錯(cuò)誤。

實(shí)現(xiàn)自己的Assert工具

既然我們先前定義了自己的BusinessException,并且在其中維護(hù)了業(yè)務(wù)錯(cuò)誤碼errCode,就沒必要用spring的Assert工具了,因?yàn)樗鼟伋鰜淼氖?code>IllegalStateException異常,最終被我們?nèi)之惓L幚砥饕宰畲蟮?code>Exception的處理邏輯進(jìn)行包裝響應(yīng)結(jié)果,自然“參數(shù)校驗(yàn)失敗”的錯(cuò)誤碼類型就丟了,因此這里我們基于spring對Assert的實(shí)現(xiàn),我們包裝為自己的Assert

package com.xiaojuan.boot.util;
import ...
public class Assert {
    public static void hasText(@Nullable String text, String message) {
        if (!StringUtils.hasText(text)) {
            throw new BusinessException(message, BusinessError.PARAM_INVALID.getValue());
        }
    }
}

controller層拋出異常

最后我們將原來預(yù)留todo注釋的地方改為拋出異常的形式:

最后,我們再基于test.http對拋出異常的測試場景進(jìn)行測試,看是否達(dá)到預(yù)期的http狀態(tài)碼和json結(jié)構(gòu),這個(gè)大家自行測試。

到此這篇關(guān)于基于spring boot實(shí)現(xiàn)一個(gè)全局異常處理器的文章就介紹到這了,更多相關(guān)spring boot全局異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java設(shè)計(jì)模式之外觀模式解析

    Java設(shè)計(jì)模式之外觀模式解析

    這篇文章主要介紹了Java設(shè)計(jì)模式之外觀模式解析,外觀模式提供了一個(gè)統(tǒng)一的接口,用來訪問子系統(tǒng)中的一群接口,外觀定義了一個(gè)高層接口,讓子系統(tǒng)更容易使用,需要的朋友可以參考下
    2024-01-01
  • java音樂播放器實(shí)現(xiàn)代碼

    java音樂播放器實(shí)現(xiàn)代碼

    這篇文章主要介紹了java音樂播放器的實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 學(xué)習(xí)Java之如何正確地跳出循環(huán)結(jié)構(gòu)

    學(xué)習(xí)Java之如何正確地跳出循環(huán)結(jié)構(gòu)

    我們在利用循環(huán)執(zhí)行重復(fù)操作的過程中,存在著一個(gè)需求:如何中止,或者說提前結(jié)束一個(gè)循環(huán),所以就給大家講解一下,如何在java代碼中返回一個(gè)結(jié)果,如何結(jié)束和跳出一個(gè)循環(huán),需要的朋友可以參考下
    2023-05-05
  • Java本地方法(JNA)詳解及常見問題

    Java本地方法(JNA)詳解及常見問題

    JNA(Java?Native?Access)是一個(gè)開源Java框架,用于無需編寫JNI代碼即可動態(tài)訪問本地系統(tǒng)庫如Windows的dll,它允許Java程序直接調(diào)用本地方法,這篇文章主要介紹了Java本地方法(JNA)詳解及常見問題,需要的朋友可以參考下
    2024-09-09
  • 100行java寫的微信跳一跳輔助程序

    100行java寫的微信跳一跳輔助程序

    本篇文章給大家分享了用java寫的一個(gè)微信跳一跳輔助腳本程序,有興趣的朋友參考學(xué)習(xí)下。
    2018-01-01
  • java實(shí)戰(zhàn)之桌球小游戲

    java實(shí)戰(zhàn)之桌球小游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)戰(zhàn)之桌球小游戲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • SpringBoot2 task scheduler 定時(shí)任務(wù)調(diào)度器四種方式

    SpringBoot2 task scheduler 定時(shí)任務(wù)調(diào)度器四種方式

    這篇文章主要介紹了SpringBoot2 task scheduler 定時(shí)任務(wù)調(diào)度器四種方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 每日六道java新手入門面試題,通往自由的道路--線程池

    每日六道java新手入門面試題,通往自由的道路--線程池

    這篇文章主要為大家分享了最有價(jià)值的6道線程池面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,對hashCode方法的設(shè)計(jì)、垃圾收集的堆和代進(jìn)行剖析,感興趣的小伙伴們可以參考一下
    2021-06-06
  • 一篇文章徹底拆解Java?HashMap擴(kuò)容機(jī)制

    一篇文章徹底拆解Java?HashMap擴(kuò)容機(jī)制

    在Java中HashMap是一個(gè)非常常用的數(shù)據(jù)結(jié)構(gòu),基于哈希表實(shí)現(xiàn),它通過鍵值對的形式存儲數(shù)據(jù),這篇文章主要介紹了Java HashMap擴(kuò)容機(jī)制的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2026-04-04
  • Java之jdbc連接mysql數(shù)據(jù)庫的方法步驟詳解

    Java之jdbc連接mysql數(shù)據(jù)庫的方法步驟詳解

    這篇文章主要介紹了Java之jdbc連接mysql數(shù)據(jù)庫的方法步驟詳解,JCBC技術(shù)是java開發(fā)必備的只是,jdbc連接mysql數(shù)據(jù)庫,這是一個(gè)比較簡單的方法,有興趣的可以了解一下
    2020-07-07

最新評論

曲周县| 安义县| 广平县| 泾阳县| 乌什县| 肃宁县| 盐城市| 扶余县| 昌乐县| 桦南县| 凌海市| 天镇县| 唐山市| 昔阳县| 鸡西市| 都昌县| 邢台县| 湾仔区| 朝阳市| 班玛县| 廉江市| 龙海市| 沁水县| 丹寨县| 铜陵市| 石嘴山市| 密云县| 伊金霍洛旗| 建宁县| 观塘区| 苍梧县| 铜鼓县| 江安县| 河源市| 长汀县| 阳春市| 榆林市| 永新县| 云梦县| 洱源县| 会东县|