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

SpringBoot的全局異常攔截實(shí)踐過(guò)程

 更新時(shí)間:2025年12月12日 14:23:00   作者:無(wú)語(yǔ)堵上西樓  
SpringBoot中使用@ControllerAdvice和@ExceptionHandler實(shí)現(xiàn)全局異常攔截,@RestControllerAdvice默認(rèn)返回JSON格式,@ResponseStatus指定HTTP狀態(tài)碼,@ExceptionHandler捕獲異常,自定義BusinessException和HttpCodeEnum類(lèi),便于統(tǒng)一異常處理和返回格式

在 Spring Boot 中,可以通過(guò)使用 @ControllerAdvice 注解和 @ExceptionHandler 注解來(lái)實(shí)現(xiàn)全局異常攔截。

@RestControllerAdvice

@RestControllerAdvice 是 Spring Framework 提供的注解,用于定義全局異常處理類(lèi),并且結(jié)合 @ExceptionHandler 注解來(lái)處理異常。與 @ControllerAdvice 不同的是,@RestControllerAdvice 默認(rèn)情況下會(huì)將返回值轉(zhuǎn)換為 JSON 格式。

@RestControllerAdvice
public class GlobalExceptionHandler {
    
  //.....攔截異常方法

}

@ResponseStatus(...)

@ResponseStatus(HttpStatus.BAD_REQUEST) 是一個(gè)注解,用于在異常處理方法上指定特定的HTTP狀態(tài)碼。當(dāng)該異常被拋出時(shí),將返回指定的HTTP狀態(tài)碼給客戶(hù)端。

@RestControllerAdvice
public class GlobalExceptionHandler {
    
  //.....攔截異常方法
  /**
     * 缺少請(qǐng)求體異常處理器
     * @param e 缺少請(qǐng)求體異常 使用get方式請(qǐng)求 而實(shí)體使用@RequestBody修飾
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
        String requestURI = httpServletRequest.getRequestURI();
        log.error("請(qǐng)求地址'{}',請(qǐng)求體缺失'{}'", requestURI, e.getMessage());
        return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);
    }
}

@ExceptionHandler(...)

@ExceptionHandler(...) 是一個(gè)異常處理注解,用于捕獲請(qǐng)求的異常。當(dāng)客戶(hù)端發(fā)送的請(qǐng)求消息無(wú)法被框架正確解析時(shí),將拋出該異常并調(diào)用對(duì)應(yīng)的異常處理方法。

@RestControllerAdvice
public class GlobalExceptionHandler {
    
  //.....攔截異常方法
  /**
     * 缺少請(qǐng)求體異常處理器
     * @param e 缺少請(qǐng)求體異常 使用get方式請(qǐng)求 而實(shí)體使用@RequestBody修飾
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
        String requestURI = httpServletRequest.getRequestURI();
        log.error("請(qǐng)求地址'{}',請(qǐng)求體缺失'{}'", requestURI, e.getMessage());
        return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);
    }
}

RuntimeException

RuntimeException 是 Java 提供的一個(gè)運(yùn)行時(shí)異常類(lèi)。與受檢查異常不同,運(yùn)行時(shí)異常不需要在方法聲明中顯式地聲明或捕獲,并且在運(yùn)行時(shí)拋出時(shí)也不需要強(qiáng)制捕獲或處理。所以我們可以在全局異常捕獲中去捕獲這個(gè)異常

public class BusinessException extends RuntimeException {

    private int code;
    //使用枚舉構(gòu)造
    public BusinessException(HttpCodeEnum httpCodeEnum){
        super(httpCodeEnum.getMsg());
        this.code=httpCodeEnum.getCode();
    }
    //使用自定義消息體
    public BusinessException(HttpCodeEnum httpCodeEnum, String msg){
        super(msg);
        this.code=httpCodeEnum.getCode();
    }

    //根據(jù)異常構(gòu)造
    public BusinessException(HttpCodeEnum httpCodeEnum, Throwable msg){
        super(msg);
        this.code=httpCodeEnum.getCode();
    }


}

 上述代碼定義了一個(gè)名為 BusinessException 的自定義異常類(lèi),它繼承自 RuntimeException。

這個(gè)自定義異常類(lèi)具有以下特點(diǎn):

  1. 包含了一個(gè) code 字段,用于表示異常的錯(cuò)誤碼。
  2. 提供了不同的構(gòu)造方法,以方便在拋出異常時(shí)指定錯(cuò)誤碼和錯(cuò)誤信息。
  • BusinessException(HttpCodeEnum httpCodeEnum) 構(gòu)造方法使用枚舉類(lèi)型 HttpCodeEnum 來(lái)設(shè)置異常的錯(cuò)誤碼和錯(cuò)誤信息。
  • BusinessException(HttpCodeEnum httpCodeEnum, String msg) 構(gòu)造方法使用自定義的錯(cuò)誤信息來(lái)設(shè)置異常的錯(cuò)誤碼和錯(cuò)誤信息。
  • BusinessException(HttpCodeEnum httpCodeEnum, Throwable msg) 構(gòu)造方法使用其他異常的實(shí)例來(lái)設(shè)置異常的錯(cuò)誤碼,并可選地提供通過(guò) Throwable 獲取的錯(cuò)誤信息。

HttpCodeEnum枚舉類(lèi)

我們還需要一個(gè)類(lèi)表示 HTTP 響應(yīng)的狀態(tài)碼和對(duì)應(yīng)的消息 ,以下為基本的舉例查考。

public enum HttpCodeEnum {
    // 成功
    SUCCESS(200, "操作成功"),
    // 登錄
    NEED_LOGIN(401, "需要登錄后操作"),
    NO_OPERATOR_AUTH(403, "無(wú)權(quán)限操作"),
    SYSTEM_ERROR(500, "出現(xiàn)錯(cuò)誤"),
    USERNAME_EXIST(501, "用戶(hù)名已存在"),
    PHONENUMBER_EXIST(502, "手機(jī)號(hào)已存在"), EMAIL_EXIST(503, "郵箱已存在"),
    REQUIRE_USERNAME(504, "必需填寫(xiě)用戶(hù)名"),
    CONTENT_NOT_NULL(506, "評(píng)論內(nèi)容不能為空"),
    FILE_TYPE_ERROR(507, "文件類(lèi)型錯(cuò)誤"),
    USERNAME_NOT_NULL(508, "用戶(hù)名不能為空"),
    NICKNAME_NOT_NULL(509, "昵稱(chēng)不能為空"),
    PASSWORD_NOT_NULL(510, "密碼不能為空"),
    EMAIL_NOT_NULL(511, "郵箱不能為空"),
    NICKNAME_EXIST(512, "昵稱(chēng)已存在"),
    LOGIN_ERROR(505, "用戶(hù)名或密碼錯(cuò)誤");
    int code;
    String msg;

    HttpCodeEnum(int code, String errorMessage) {
        this.code = code;
        this.msg = errorMessage;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}

上述代碼定義了一個(gè) HttpCodeEnum 枚舉類(lèi),用于表示 HTTP 響應(yīng)的狀態(tài)碼和對(duì)應(yīng)的消息。

這個(gè)枚舉類(lèi)具有以下特點(diǎn):

  1. 包含一組枚舉常量,每個(gè)常量代表一個(gè) HTTP 響應(yīng)狀態(tài)。
  2. 每個(gè)常量都有一個(gè)整型的 code 和一個(gè)字符串類(lèi)型的 msg,分別表示狀態(tài)碼和對(duì)應(yīng)的消息。
  3. 提供了相應(yīng)的構(gòu)造方法、獲取 code 和 msg 的方法。

ResponseResult類(lèi)

該類(lèi)的主要作用是封裝接口返回的數(shù)據(jù),統(tǒng)一格式化輸出,方便前端調(diào)用和展示。

import lombok.Data;

import java.io.Serializable;
@Data
public class ResponseResult<T> implements Serializable {
    private Boolean success;
    private Integer code;
    private String msg;
    private T data;

    public ResponseResult() {
        this.success=true;
        this.code = HttpCodeEnum.SUCCESS.getCode();
        this.msg = HttpCodeEnum.SUCCESS.getMsg();
    }

    public ResponseResult(Integer code, T data) {
        this.code = code;
        this.data = data;
    }

    public ResponseResult(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public ResponseResult(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public static ResponseResult errorResult(int code, String msg) {
        ResponseResult result = new ResponseResult();
        return result.error(code, msg);
    }

    public static ResponseResult okResult() {
        ResponseResult result = new ResponseResult();
        return result;
    }

    public static ResponseResult okResult(int code, String msg) {
        ResponseResult result = new ResponseResult();
        return result.ok(code, null, msg);
    }




    public static ResponseResult setHttpCodeEnum(HttpCodeEnum enums) {
        return okResult(enums.getCode(), enums.getMsg());
    }


    public ResponseResult<?> error(Integer code, String msg) {
        this.success=false;
        this.code = code;
        this.msg = msg;
        return this;
    }

    public ResponseResult<?> ok(Integer code, T data) {
        this.success=true;
        this.code = code;
        this.data = data;
        return this;
    }

    public ResponseResult<?> ok(Integer code, T data, String msg) {
        this.success=true;
        this.code = code;
        this.data = data;
        this.msg = msg;
        return this;
    }

    public ResponseResult<?> ok(T data) {
        this.success=true;
        this.data = data;
        return this;
    }


}

全局異常捕獲

全局異常捕獲是一種處理應(yīng)用程序中未處理的異常的機(jī)制,它可以統(tǒng)一處理應(yīng)用程序中的異常,避免異常導(dǎo)致程序崩潰或向用戶(hù)顯示不友好的錯(cuò)誤信息。我們可以通過(guò)上述的解釋去捕獲異常,定義code類(lèi)型枚舉返回ResponseResult給前端

import com.example.demo.util.HttpCodeEnum;
import com.example.demo.util.ResponseResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

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

@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @Autowired
    private HttpServletRequest httpServletRequest;

    private final String sysError="系統(tǒng)出錯(cuò)";

    /**
     * 缺少請(qǐng)求體異常處理器
     * @param e 缺少請(qǐng)求體異常 使用get方式請(qǐng)求 而實(shí)體使用@RequestBody修飾
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
        String requestURI = httpServletRequest.getRequestURI();
        log.error("請(qǐng)求地址'{}',請(qǐng)求體缺失'{}'", requestURI, e.getMessage());
        return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);
    }

    /*
     * @Description:  捕獲請(qǐng)求方法異常,比如post接口使用了get
     */
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseResult methodNotAllowedHandler(HttpRequestMethodNotSupportedException e) {
        String requestURI = httpServletRequest.getRequestURI();
        log.error("請(qǐng)求地址'{}',請(qǐng)求方法不被允許'{}'", requestURI, e.getMessage());
        return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);
    }

    // get請(qǐng)求的對(duì)象參數(shù)校驗(yàn)異常
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public ResponseResult bindExceptionHandler(MissingServletRequestParameterException e) {
            String requestURI = httpServletRequest.getRequestURI();
        log.error("請(qǐng)求地址'{}',get方式請(qǐng)求參數(shù)'{}'必傳", requestURI, e.getParameterName());
            return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);
    }
    // post請(qǐng)求的對(duì)象參數(shù)校驗(yàn)異常
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public ResponseResult methodArgumentNotValidHandler(MethodArgumentNotValidException e) {
        String requestURI = httpServletRequest.getRequestURI();
        log.error("請(qǐng)求地址'{}',post方式請(qǐng)求參數(shù)異常'{}'", requestURI, e.getMessage());
            List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
            return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), getValidExceptionMsg(allErrors));
    }

    // 業(yè)務(wù)類(lèi)異常
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(BusinessException.class)
    public ResponseResult businessExceptionHandler(BusinessException e) {
        String requestURI = httpServletRequest.getRequestURI();
        System.out.println(e);
        log.error("請(qǐng)求地址'{}',捕獲業(yè)務(wù)類(lèi)異常'{}'", requestURI,e.getMessage());
        return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage());
    }
    // 運(yùn)行時(shí)異常
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(RuntimeException.class)
    public ResponseResult runtimeExceptionHandler(RuntimeException e) {
        String requestURI = httpServletRequest.getRequestURI();
        log.error("請(qǐng)求地址'{}',捕獲運(yùn)行時(shí)異常'{}'", requestURI, e.getMessage());
        return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage());
    }
    // 系統(tǒng)級(jí)別異常
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Throwable.class)
    public ResponseResult throwableExceptionHandler(Throwable e) {
        String requestURI = httpServletRequest.getRequestURI();
        log.error("請(qǐng)求地址'{}',捕獲系統(tǒng)級(jí)別異常'{}'", requestURI,e.getMessage());
        return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage());
    }



    private String getValidExceptionMsg(List<ObjectError> errors) {
        if(!CollectionUtils.isEmpty(errors)){
            StringBuilder sb = new StringBuilder();
            errors.forEach(error -> {
                if (error instanceof FieldError) {
                    sb.append(((FieldError)error).getField()).append(":");
                }
                sb.append(error.getDefaultMessage()).append(";");
            });
            String msg = sb.toString();
            msg = msg.substring(0, msg.length() -1);
            return msg;
        }
        return null;
    }

}

測(cè)試

入?yún)⒉徽_時(shí)

發(fā)出請(qǐng)求

返回結(jié)果

捕獲異常

運(yùn)行時(shí)錯(cuò)誤

發(fā)起請(qǐng)求

返回結(jié)果

捕獲異常

業(yè)務(wù)異常

發(fā)送請(qǐng)求

返回結(jié)果

捕獲異常

總結(jié)

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

相關(guān)文章

  • MyBatisPlus自定義SQL的實(shí)現(xiàn)

    MyBatisPlus自定義SQL的實(shí)現(xiàn)

    MyBatisPlus提供了自定義SQL功能,允許開(kāi)發(fā)者在Mapper接口中定義方法,并通過(guò)XML文件或注解編寫(xiě)SQL語(yǔ)句,本文詳解了如何在MP中使用自定義SQL,感興趣的可以了解一下
    2024-09-09
  • SpringBoot松散綁定/寬松綁定(Relaxed Binding)的實(shí)現(xiàn)

    SpringBoot松散綁定/寬松綁定(Relaxed Binding)的實(shí)現(xiàn)

    本文主要介紹了SpringBoot松散綁定/寬松綁定(Relaxed Binding)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-08-08
  • spring中對(duì)象注入的三種實(shí)現(xiàn)方式

    spring中對(duì)象注入的三種實(shí)現(xiàn)方式

    本文主要介紹了spring中對(duì)象注入的三種實(shí)現(xiàn)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • java中“==“和equals()的區(qū)別詳解

    java中“==“和equals()的區(qū)別詳解

    這篇文章主要給大家介紹了關(guān)于java中“==“和equals()區(qū)別的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 在java poi導(dǎo)入Excel通用工具類(lèi)示例詳解

    在java poi導(dǎo)入Excel通用工具類(lèi)示例詳解

    這篇文章主要給大家介紹了關(guān)于在java poi導(dǎo)入Excel通用工具類(lèi)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • 淺談Java StringBuilder為什么線程不安全

    淺談Java StringBuilder為什么線程不安全

    這篇文章主要介紹了淺談Java StringBuilder為什么線程不安全,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Java Ribbon負(fù)載均衡詳細(xì)講解

    Java Ribbon負(fù)載均衡詳細(xì)講解

    Ribbon其實(shí)就是一個(gè)軟負(fù)載均衡的客戶(hù)端組件,他可以和其他所需請(qǐng)求的客戶(hù)端結(jié)合使用,這篇文章主要介紹了Ribbon負(fù)載均衡服務(wù)調(diào)用案例代碼,需要的朋友可以參考下
    2023-01-01
  • Spring很常用的@Conditional注解的使用場(chǎng)景和源碼解析

    Spring很常用的@Conditional注解的使用場(chǎng)景和源碼解析

    今天要分享的是Spring的注解@Conditional,@Conditional是一個(gè)條件注解,它的作用是判斷Bean是否滿(mǎn)足條件,本文詳細(xì)介紹了@Conditional注解的使用場(chǎng)景和源碼,需要的朋友可以參考一下
    2023-04-04
  • java實(shí)現(xiàn)微信搶紅包算法

    java實(shí)現(xiàn)微信搶紅包算法

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)微信搶紅包算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • SpringBoot自定義RestTemplate的攔截器鏈的實(shí)戰(zhàn)指南

    SpringBoot自定義RestTemplate的攔截器鏈的實(shí)戰(zhàn)指南

    在項(xiàng)目開(kāi)發(fā)中,RestTemplate作為Spring提供的HTTP客戶(hù)端工具,經(jīng)常用于訪問(wèn)內(nèi)部或三方服務(wù),但在實(shí)際項(xiàng)目中,我們往往需要對(duì)請(qǐng)求進(jìn)行統(tǒng)一處理,所以本文給大家介紹了SpringBoot自定義RestTemplate的攔截器鏈的實(shí)戰(zhàn)指南,需要的朋友可以參考下
    2025-07-07

最新評(píng)論

皮山县| 内乡县| 库车县| 吕梁市| 盱眙县| 文山县| 玛多县| 银川市| 沭阳县| 台前县| 长顺县| 黄山市| 永登县| 张北县| 密山市| 张家口市| 建平县| 和林格尔县| 孝义市| 当阳市| 林西县| 文山县| 广南县| 鄱阳县| 图们市| 江阴市| 专栏| 平定县| 梅河口市| 延庆县| 扎赉特旗| 凤冈县| 三原县| 栾城县| 上栗县| 平阳县| 仁化县| 阜南县| 清远市| 潼南县| 柳河县|