欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot?實(shí)現(xiàn)全局異常處理的示例代碼

 更新時(shí)間:2024年06月25日 08:30:03   作者:Excellent的崽子  
本文主要介紹了SpringBoot實(shí)現(xiàn)全局異常處理,全局異常處理器的使用可以顯著提高Spring Boot項(xiàng)目的代碼質(zhì)量和可維護(hù)性,減少冗余代碼,具有一定的參考價(jià)值,感興趣的可以了解一下

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

  • 減少冗余代碼: 在不使用全局異常處理器的情況下,項(xiàng)目中各層可能會(huì)出現(xiàn)大量的try {…} catch {…} finally {…}代碼塊,這些代碼塊不僅冗余,還影響代碼的可讀性。全局異常處理器允許我們?cè)谝粋€(gè)獨(dú)立的類中定義對(duì)所有控制器異常的處理機(jī)制,從而消除大部分try-catch塊。
  • 統(tǒng)一異常處理: 全局異常處理器可以將異常按階段(如進(jìn)入Controller前的異常和Service層異常)進(jìn)行分類處理,提供統(tǒng)一的異常處理策略。
  • 自定義異常處理: 對(duì)于自定義的異常,使用全局異常處理器可以更容易地進(jìn)行捕獲和處理,而不是在每個(gè)可能拋出異常的地方都寫一遍處理邏輯。
  • 客戶端友好性: 直接拋出異常給客戶端可能會(huì)導(dǎo)致客戶端無(wú)法理解異常信息。全局異常處理器允許我們將異常轉(zhuǎn)換為客戶端可理解的格式(如JSON響應(yīng)),提高用戶體驗(yàn)。

總結(jié):全局異常處理器的使用可以顯著提高Spring Boot項(xiàng)目的代碼質(zhì)量和可維護(hù)性,減少冗余代碼,提高代碼的可讀性和可維護(hù)性,統(tǒng)一異常處理策略,并提高客戶端體驗(yàn)。因此,在Spring Boot項(xiàng)目中,使用全局異常處理器是一個(gè)值得推薦的做法。

代碼實(shí)戰(zhàn)

首先我們需要在項(xiàng)目中創(chuàng)建一個(gè)全局異常處理器類,比如叫 GlobalExceptionHandler,在該類上面需要加上 @RestControllerAdvice 注解表示這是一個(gè)全局異常處理器,代碼示例:

import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

/**
 * 全局異常處理器
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    public final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 攔截參數(shù)驗(yàn)證異常
     */
    @SneakyThrows
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public AjaxResult validExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        FieldError firstFieldError = CollectionUtil.getFirst(bindingResult.getFieldErrors());
        String exceptionStr = Optional.ofNullable(firstFieldError)
                .map(FieldError::getDefaultMessage)
                .orElse(StrUtil.EMPTY);
        logger.error("[{}] {} [ex] {}", request.getMethod(), getUrl(request), exceptionStr);
        return AjaxResult.error(exceptionStr);
    }

    /**
     * 攔截業(yè)務(wù)異常
     * BusinessServiceException 是一個(gè)自定義異常,以你們項(xiàng)目中的自定義異常為準(zhǔn),如果沒有可以不寫
     */
    @ExceptionHandler(value = {BusinessServiceException.class})
    public AjaxResult handleBusinessException(HttpServletRequest request, BusinessServiceException ex){
        String exceptionStr = ex.getMessage();
        logger.error("[{}] {} [ex] {}", request.getMethod(), getUrl(request), exceptionStr);
        return AjaxResult.error(exceptionStr);
    }

    /**
     * 攔截未捕獲異常
     */
    @ExceptionHandler(Throwable.class)
    public AjaxResult defaultErrorHandler(HttpServletRequest request, Throwable throwable) {
        logger.error("[{}] {} ", request.getMethod(), getUrl(request), throwable);
        return AjaxResult.error(throwable.getMessage());
    }

    private String getUrl(HttpServletRequest request) {
        if (StringUtils.isEmpty(request.getQueryString())) {
            return request.getRequestURL().toString();
        }
        return request.getRequestURL().toString() + "?" + request.getQueryString();
    }
}

到這里,全局異常處理器就已經(jīng)寫完了,接下來(lái)就是驗(yàn)證環(huán)節(jié)。我會(huì)依次驗(yàn)證每一個(gè)異常場(chǎng)景是否可以成功攔截。
在驗(yàn)證之前,我們先來(lái)看一張圖:

image.png

上面這張圖片大家應(yīng)該都很熟悉,這就是在不對(duì)接口中的異常進(jìn)行處理時(shí) SpringBoot 默認(rèn)返回的頁(yè)面,如果我們的異常處理器生效了,那么返回的就應(yīng)該是我們封裝好的數(shù)據(jù)。

驗(yàn)證 MethodArgumentNotValidException 異常

在驗(yàn)證 MethodArgumentNotValidException 異常前,需要先說(shuō)明一下該異常常見的觸發(fā)場(chǎng)景:

  • 數(shù)據(jù)轉(zhuǎn)換問(wèn)題:當(dāng)客戶端傳遞的數(shù)據(jù)類型無(wú)法正確轉(zhuǎn)換為方法參數(shù)的類型時(shí),會(huì)發(fā)生數(shù)據(jù)轉(zhuǎn)換問(wèn)題,導(dǎo)致MethodArgumentNotValidException異常。這通常發(fā)生在使用@RequestBody注解處理JSON請(qǐng)求體時(shí),如果JSON格式不正確或無(wú)法映射到目標(biāo)對(duì)象,就會(huì)拋出此異常。
  • 錯(cuò)誤的驗(yàn)證注解: 如果在實(shí)體類中對(duì)屬性使用了不符合驗(yàn)證需求的注解,如@NotNull、@Size等,并且請(qǐng)求中的數(shù)據(jù)不符合這些注解指定的規(guī)則,那么在Spring MVC將請(qǐng)求參數(shù)解析為控制器方法參數(shù)時(shí)會(huì)觸發(fā)校驗(yàn),并拋出MethodArgumentNotValidException異常。
  • 未通過(guò)校驗(yàn)的參數(shù): 當(dāng)使用@Valid或@Validated注解對(duì)方法參數(shù)進(jìn)行校驗(yàn)時(shí),如果參數(shù)不符合校驗(yàn)規(guī)則(如非空、長(zhǎng)度、格式等),會(huì)拋出MethodArgumentNotValidException異常。例如,一個(gè)表單提交到Controller時(shí),如果表單中的某個(gè)字段不符合校驗(yàn)規(guī)則,則會(huì)拋出此異常。

接下來(lái)我們創(chuàng)建一個(gè) UserEntity 類做為方法參數(shù)用來(lái)測(cè)試:

import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Data
public class UserEntity {

    @NotNull(message = "用戶ID不能為空")
    private Long userId;

    @NotNull(message = "用戶名不能為空")
    @Size(min = 2, max = 30, message = "用戶名長(zhǎng)度必須在2到30個(gè)字符之間")
    private String username;
    
}

// 注意,這個(gè)方法我們并沒有采取任何 try catch 操作
@PostMapping("/test")
public AjaxResult Test(HttpServletRequest request, @RequestBody @Valid UserEntity userEntity) {
        Map<String,Object> model = new HashMap<String,Object>();
        String planCode = request.getParameter("planCode");
        String planDefineId = request.getParameter("planDefineId");
        if (StringUtils.isBlank(planDefineId) || StringUtils.isBlank(planCode)) {
            throw new BusinessServiceException("參數(shù)不可以為空!");
        }
        // 獲取信息
        String planName = retailProductCommon.getproductName(planCode, planDefineId);
        model.put("planName", planName);
        return AjaxResult.success(model);
}

這里我們使用 PostMan 工具去請(qǐng)求這個(gè)接口,并設(shè)置一個(gè)不滿足要求的參數(shù),看下是否會(huì)以為拋錯(cuò)導(dǎo)致程序中斷。請(qǐng)求結(jié)果:

image.png

可以發(fā)現(xiàn),正常返回錯(cuò)誤信息給客戶端了,并沒有直接拋500。

驗(yàn)證自定義異常

驗(yàn)證 BusinessServiceException 異常也很簡(jiǎn)單,我們將上面 UserEntity 的參數(shù)補(bǔ)全,但是代碼中為空會(huì)拋錯(cuò)的那個(gè)兩個(gè)參數(shù)我們不傳,看下會(huì)有什么結(jié)果。請(qǐng)求結(jié)果:

image.png

這里同樣是我們自定義的返回對(duì)象,并不是SpringBoot默認(rèn)的500頁(yè)面,所以驗(yàn)證成功。

驗(yàn)證其他異常

接下來(lái)我們?cè)?test 接口中手動(dòng)寫一個(gè)異常代碼出來(lái),比如int num = 1/0當(dāng)代碼執(zhí)行到這里的時(shí)候會(huì)拋出 / by zero,我們看下結(jié)果如何,會(huì)不會(huì)被 defaultErrorHandler 方法攔截:

image.png

這里同樣是我們自定義的返回對(duì)象,并不是SpringBoot默認(rèn)的500頁(yè)面,所以驗(yàn)證成功。

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

相關(guān)文章

  • jdk線程池的實(shí)現(xiàn)

    jdk線程池的實(shí)現(xiàn)

    本文主要介紹了jdk線程池的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Java中的阻塞隊(duì)列詳細(xì)介紹

    Java中的阻塞隊(duì)列詳細(xì)介紹

    這篇文章主要介紹了Java中的阻塞隊(duì)列詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • Java按照List內(nèi)存儲(chǔ)的對(duì)象的某個(gè)字段進(jìn)行排序的實(shí)例

    Java按照List內(nèi)存儲(chǔ)的對(duì)象的某個(gè)字段進(jìn)行排序的實(shí)例

    下面小編就為大家?guī)?lái)一篇Java按照List內(nèi)存儲(chǔ)的對(duì)象的某個(gè)字段進(jìn)行排序的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-12-12
  • spring boot整合mybatis利用Mysql實(shí)現(xiàn)主鍵UUID的方法

    spring boot整合mybatis利用Mysql實(shí)現(xiàn)主鍵UUID的方法

    這篇文章主要給大家介紹了關(guān)于spring boot整合mybatis利用Mysql實(shí)現(xiàn)主鍵UUID的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03
  • maven項(xiàng)目后出現(xiàn)‘parent.relativePath’ of POM錯(cuò)誤時(shí)的解決方法

    maven項(xiàng)目后出現(xiàn)‘parent.relativePath’ of POM錯(cuò)誤時(shí)的解決方法

    在Springboot項(xiàng)目啟動(dòng)時(shí),項(xiàng)目報(bào)錯(cuò)‘parent.relativePath’ of POM問(wèn)題,項(xiàng)目無(wú)法正常啟動(dòng),本文就來(lái)介紹一下解決方法,感興趣的可以了解一下
    2023-10-10
  • Mybatis中自定義實(shí)例化SqlSessionFactoryBean問(wèn)題

    Mybatis中自定義實(shí)例化SqlSessionFactoryBean問(wèn)題

    這篇文章主要介紹了Mybatis中自定義實(shí)例化SqlSessionFactoryBean問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Java中FileWriter類的簡(jiǎn)介說(shuō)明

    Java中FileWriter類的簡(jiǎn)介說(shuō)明

    這篇文章主要介紹了Java中FileWriter類的簡(jiǎn)介說(shuō)明,FileWriter類提供了多種寫入字符的方法,包括寫入單個(gè)字符、寫入字符數(shù)組和寫入字符串等,它還提供了一些其他的方法,如刷新緩沖區(qū)、關(guān)閉文件等,需要的朋友可以參考下
    2023-10-10
  • java實(shí)現(xiàn)稀疏矩陣的壓縮與解壓的方法

    java實(shí)現(xiàn)稀疏矩陣的壓縮與解壓的方法

    這篇文章主要介紹了java實(shí)現(xiàn)稀疏矩陣的壓縮與解壓 ,把該稀疏矩陣壓縮以三元組形式表示并以文件形式保存,再寫另一個(gè)程序讀取文件中的信息把壓縮后的三元組還原成原來(lái)的稀疏矩陣,需要的朋友可以參考下
    2022-03-03
  • Java使用jacob將微軟office中word、excel、ppt轉(zhuǎn)成pdf

    Java使用jacob將微軟office中word、excel、ppt轉(zhuǎn)成pdf

    這篇文章主要為大家詳細(xì)介紹了Java使用jacob將微軟office中word、excel、ppt轉(zhuǎn)成pdf,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • maven-compiler-plugin版本指定方式

    maven-compiler-plugin版本指定方式

    這篇文章主要介紹了maven-compiler-plugin版本指定方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01

最新評(píng)論