GlobalExceptionHandler 自定義異常類 + 處理validation的異常

在 Spring Boot 項目中,?自定義異常通常用于處理特定的業務邏輯錯誤,并結合全局異常處理器(@ControllerAdvice)統一返回結構化的錯誤信息。

一.全局異常處理器:?

1. 自定義異常類?

定義一個繼承自?RuntimeException?的業務異常類,包含錯誤碼和錯誤信息:

public class BusinessException extends RuntimeException {private final int code; // 自定義錯誤碼private final String message; // 錯誤信息public BusinessException(int code, String message) {super(message);this.code = code;this.message = message;}// 使用枚舉定義錯誤類型(推薦)public BusinessException(ErrorCode errorCode) {super(errorCode.getMessage());this.code = errorCode.getCode();this.message = errorCode.getMessage();}// Getterpublic int getCode() { return code; }@Override public String getMessage() { return message; }
}
?配套的枚舉:
public enum ErrorCode {USER_NOT_FOUND(1001, "用戶不存在"),INVALID_PARAM(1002, "參數無效"),INTERNAL_ERROR(5000, "系統內部錯誤");private final int code;private final String message;ErrorCode(int code, String message) {this.code = code;this.message = message;}// Getterpublic int getCode() { return code; }public String getMessage() { return message; }
}

2. 全局異常處理器?

使用?@ControllerAdvice?捕獲異常并統一返回 JSON 格式的錯誤響應:

@Slf4j
@ControllerAdvice  // 標記該類為全局異常處理器,可以攔截所有Controller拋出的異常
@ResponseBody // 或直接使用 @RestControllerAdvice
public class GlobalExceptionHandler {/?**?* 處理業務異常*/@ExceptionHandler(BusinessException.class) // 處理自定義異常BusinessException@ResponseStatus(HttpStatus.BAD_REQUEST) // 指定HTTP響應的狀態碼 400 錯誤public Result<Void> handleBusinessException(BusinessException e) {log.error("業務異常: code={}, message={}", e.getCode(), e.getMessage());return Result.fail(e.getCode(), e.getMessage());}/?**?* 處理系統異常(兜底)*/@ExceptionHandler(Exception.class)  // 處理所有未被其他處理器捕獲的異常@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) // 指定HTTP響應的狀態碼 500 錯誤public Result<Void> handleException(Exception e) {log.error("系統異常: ", e);return Result.fail(ErrorCode.INTERNAL_ERROR.getCode(), "系統繁忙,請稍后重試");}
}
統一的響應封裝類:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {private int code;private String message;private T data;// 成功響應public static <T> Result<T> success(T data) {return new Result<>(200, "成功", data);}// 失敗響應public static <T> Result<T> fail(int code, String message) {return new Result<>(code, message, null);}
}

3. 在業務代碼中拋出異常:

@RestController
@RequestMapping("/user")
public class UserController {@GetMapping("/{id}")public Result<User> getUser(@PathVariable Long id) {User user = userService.findById(id);if (user == null) {throw new BusinessException(ErrorCode.USER_NOT_FOUND); // 拋出業務異常}return Result.success(user);}
}

4.使用方法:

throw new BusinessException(1001, "用戶不存在");
throw new BusinessException(ErrorCode.USER_NOT_FOUND);

二.對于JSR303校驗的異常處理:

早在JavaEE6規范中就定義了參數校驗的規范,它就是JSR-303,它定義了Bean Validation,即對bean屬性進行校驗。

SpringBoot提供了JSR-303的支持,它就是spring-boot-starter-validation,它的底層使用Hibernate Validator,Hibernate Validator是Bean Validation 的參考實現。

所以,我們準備在Controller層使用spring-boot-starter-validation完成對請求參數的基本合法性進行校驗。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>

在javax.validation.constraints包下有很多這樣的校驗注解,直接使用注解定義校驗規則即可。

例子如下:

package com.xuecheng.content.model.dto;import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.ToString;/*** @description 添加課程dto* @author Mr.M* @date 2022/9/7 17:40* @version 1.0*/
@Data
@ToString
@Schema(name = "AddCourseDto", description = "新增課程基本信息")
public class AddCourseDto {@NotEmpty(message = "課程名稱不能為空")@Schema(description = "課程名稱", required = true)private String name;@NotEmpty(message = "適用人群不能為空")@Size(message = "適用人群內容過少",min = 10)@Schema(description = "適用人群", required = true)private String users;@NotEmpty(message = "課程分類不能為空")@Schema(description = "大分類", required = true)private String mt;@NotEmpty(message = "課程分類不能為空")@Schema(description = "小分類", required = true)private String st;@NotEmpty(message = "課程等級不能為空")@Schema(description = "課程等級", required = true)private String grade;@Schema(description = "教學模式(普通,錄播,直播等)", required = true)private String teachmode;@Schema(description = "課程介紹")private String description;@Schema(description = "課程圖片", required = true)private String pic;@NotEmpty(message = "收費規則不能為空")@Schema(description = "收費規則,對應數據字典", required = true)private String charge;
}

?上邊用到了@NotEmpty和@Size兩個注解,@NotEmpty表示屬性不能為空,@Size表示限制屬性內容的長短。

定義好校驗規則還需要開啟校驗,在controller方法中添加@Validated注解,如下:

@Operation("新增課程基礎信息")
@PostMapping("/course")
public CourseBaseInfoDto createCourseBase(@RequestBody @Validated AddCourseDto addCourseDto){//機構id,由于認證系統沒有上線暫時硬編碼Long companyId = 1L;return courseBaseInfoService.createCourseBase(companyId,addCourseDto);
}

如果校驗出錯Spring會拋出MethodArgumentNotValidException異常,我們需要在統一異常處理器中捕獲異常,解析出異常信息。

@ResponseBody
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestErrorResponse methodArgumentNotValidException(MethodArgumentNotValidException e) {// 拿到校驗框架BindingResult bindingResult = e.getBindingResult();List<String> msgList = new ArrayList<>();// 將錯誤信息放在msgListbindingResult.getFieldErrors().stream().forEach(item->msgList.add(item.getDefaultMessage()));// 將msgList的錯誤拼接String msg = StringUtils.join(msgList, ",");log.error("【系統異常】{}",msg);return new RestErrorResponse(msg);
}

有時候在同一個屬性上設置一個校驗規則不能滿足要求,比如:訂單編號由系統生成,在添加訂單時要求訂單編號為空,在更新訂單時要求訂單編寫不能為空。

此時就用到了分組校驗,同一個屬性定義多個校驗規則屬于不同的分組,比如:添加訂單定義@NULL 規則屬于 insert 分組,更新訂單定義@NotEmpty規則屬于 update 分組,insert 和update 是分組的名稱,是可以修改的。

下邊舉例說明,我們用class類型來表示不同的分組,所以我們定義不同的接口類型(空接口)表示不同的分組,由于校驗分組是公用的,所以定義在 base工程中。如下:

package com.xuecheng.base.execption;/*** @description 校驗分組* @version 1.0*/
public class ValidationGroups {public interface Inster{};public interface Update{};public interface Delete{};}

下邊在定義校驗規則時指定分組:

@NotEmpty(groups = {ValidationGroups.Inster.class},message = "添加課程名稱不能為空")
@NotEmpty(groups = {ValidationGroups.Update.class},message = "修改課程名稱不能為空")
// @NotEmpty(message = "課程名稱不能為空")
@ApiModelProperty(value = "課程名稱", required = true)
private String name;

在Controller方法中啟動校驗規則指定要使用的分組名:

@Operation("新增課程基礎信息")
@PostMapping("/course")
public CourseBaseInfoDto createCourseBase(@RequestBody @Validated({ValidationGroups.Inster.class}) AddCourseDto addCourseDto){//機構id,由于認證系統沒有上線暫時硬編碼Long companyId = 1L;return courseBaseInfoService.createCourseBase(companyId,addCourseDto);
}

再次測試,由于這里指定了Insert分組,所以拋出 異常信息:添加課程名稱不能為空。

如果修改分組為ValidationGroups.Update.class,異常信息為:修改課程名稱不能為空。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/907487.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/907487.shtml
英文地址,請注明出處:http://en.pswp.cn/news/907487.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

軟件測試過程中如何定位BUG

在軟件測試過程中&#xff0c;定位BUG是確保軟件質量的關鍵環節。有效的BUG定位不僅能幫助開發人員快速修復問題&#xff0c;還能提升整個軟件項目的效率。以下是軟件測試中定位BUG的系統性方法和策略&#xff1a; 一、復現BUG 步驟&#xff1a; 收集信息&#xff1a;記錄BUG…

如何優化Elasticsearch的搜索性能?

優化 Elasticsearch 的搜索性能需要從索引設計、查詢優化、硬件配置和集群調優等多方面入手。以下是系統化的優化策略和實操建議: 一、索引設計優化 1. 合理設置分片數 分片大小:單個分片建議 10-50GB(超過50GB會影響查詢性能)。分片數量: 總分片數 ≤ 節點數 1000(避免…

臺式電腦CPU天梯圖_2025年臺式電腦CPU天梯圖

CPU的選擇絕對是重中之重,它關乎了一臺電腦性能好壞。相信不少用戶,在挑選CPU的時候不知道誰強誰弱,尤其是intel和AMD兩款CPU之間。下面通過2025年臺式電腦CPU天梯圖來了解下這兩款cpu. 2025年臺式電腦CPU天梯圖 2025年臺式電腦CPU天梯圖包含了老舊型號以及12代、13代、14代…

HarmonyOS_ArkTs_API(1)

HarmonyOS_ArkTs_API(1) 概述 此API服務模塊是獨自開發的應用程序的核心骨架&#xff0c;提供了鴻蒙OS ArkTS客戶端組件和Java Spring Boot后端之間的強大通信接口。該模塊采用清晰的架構方法處理所有HTTP請求、響應解析和錯誤處理&#xff0c;確保系統各部分間通信的一致性和…

matlab雷達定位仿真

一、邊掃描邊跟蹤雷達仿真 邊掃描邊跟蹤&#xff08;BISTAR&#xff09;雷達仿真是一種實時雷達信號處理的技術&#xff0c;用于模擬雷達系統的操作過程&#xff0c;特別是那些具備連續掃描能力的雷達。它的基本原理和流程可以分為以下幾個步驟&#xff1a; &#xff08;1&…

互斥鎖、自旋鎖、讀寫鎖、悲觀鎖、樂觀鎖的應用場景

一&#xff1a;并發 1.1MySQL并發事務訪問相同記錄 &#xff08;1&#xff09;讀-讀 不影響 &#xff08;2&#xff09;寫-寫 寫的數據需要一個一個來&#xff0c;排隊執行 &#xff08;3&#xff09;讀-寫 兩次讀…

KEYSIGHT N9320B是德科技N9320B頻譜分析儀

KEYSIGHT N9320B是德科技N9320B頻譜分析儀 附加功能&#xff1a; 頻率范圍&#xff1a;9 kHz 至 3 GHz 分辨率帶寬&#xff1a;10 Hz 至 1 MHz DANL&#xff1a;-130 dBm&#xff0c;-148 dBm&#xff0c;帶可選前置放大器 整體幅度精度&#xff1a;<1.5 dB 最小非零掃…

零基礎開始的網工之路第十四天------Linux程序管理

目錄 一、Linux程序與進程 1、程序,進程,線程的概念 2、程序和進程的區別 3、進程和線程的區別 二、Linux進程基礎(生命周期) 1、進程生命周期 2、父子進程的關系 三、程序管理 1、常見的軟件包類型 四、Linux操作系統啟動流程詳解 1、概述 2、啟動流程核心階段 1…

群輝(synology)NAS老機器連接出現網頁端可以進入,但是本地訪問輸入一樣的賬號密碼是出現錯誤時解決方案

群輝&#xff08;synology&#xff09;NAS老機器連接出現網頁端可以進入&#xff0c;但是本地訪問輸入一樣的賬號密碼是出現錯誤時解決方案 老機器 裝的win7 系統 登入后端網頁端的時候正常&#xff0c;但是本地訪問登入時輸入登入網頁端一樣的密碼時候出現問題解決方案 1.登…

單例模式的隱秘危機

引言 單例模式作為設計模式中的基石&#xff0c;廣泛應用于配置管理、線程池、緩存系統等關鍵場景。然而&#xff0c;許多開發者誤以為“私有構造函數”足以保障其唯一性&#xff0c;卻忽視了反射機制、對象克隆、序列化反序列化這三把“隱形利刃”——它們能繞過常規防御&…

DMBOK對比知識點對比(3)

1.數據倉庫建設方法(Inmon、Kimball) 數據倉庫建設方法(Inmon、Kimball)P293方法

Python+VR:如何讓虛擬世界更懂你?——用戶行為分析的實踐

友友們好! 我是Echo_Wish,我的的新專欄《Python進階》以及《Python!實戰!》正式啟動啦!這是專為那些渴望提升Python技能的朋友們量身打造的專欄,無論你是已經有一定基礎的開發者,還是希望深入挖掘Python潛力的愛好者,這里都將是你不可錯過的寶藏。 在這個專欄中,你將會…

游戲引擎學習第311天:支持手動排序

倉庫: https://gitee.com/mrxiao_com/2d_game_7(已滿) 新倉庫: https://gitee.com/mrxiao_com/2d_game_8 回顧并為今天的內容定下基調 我們接下來要繼續完成之前開始的工作&#xff0c;上周五開始的部分內容&#xff0c;雖然當時對最終效果還不太確定&#xff0c;但現在主要任…

數據結構第2章緒論 (竟成)

第 2 章 緒論 本章主要介紹數據結構相關的一些基本概念&#xff0c;是后續章節的基礎。我們也將 408 考試大綱中&#xff0c;關于數據結構部分的考查目標羅列在這里&#xff0c;供各位考生參考&#xff1a; 1.掌握數據結構的基本概念、基本原理和基本方法。 2.掌握數據的邏輯結…

spring boot 攔截器HandlerInterceptor 不生效的原因排查

public class UserInterceptor implements HandlerInterceptor項目添加一個攔截器&#xff0c;發現未生效 1、排查攔截本身是否注入了springbean 容器 Slf4j Component public class LoginInterceptor implements HandlerInterceptor {2、排查springboot 項目掃描范圍是否包含…

用Python繪制動態愛心:代碼解析與浪漫編程實踐

用Python繪制動態愛心:代碼解析與浪漫編程實踐 一、摘要二、整體架構流程1. 初始化配置模塊2. 幾何繪制引擎3. 動畫控制系統4. 輔助功能模塊三、技術細節解析1. Turtle性能優化2. 數學公式應用3. 顏色漸變算法4. 異常處理機制5. 動畫節奏控制四、結論與展望附:完整代碼一、摘…

WPS 免登錄解鎖編輯

遇到 WPS 需要登錄才能啟用編輯功能&#xff1f; 如何免登錄使用編輯功能&#xff1f; 方法一 解鎖方法 1、關閉 WPS&#xff1b; 2、桌面右鍵→ “新建”→“文本文檔”&#xff0c;粘貼以下內容&#xff08;見最下面&#xff09;&#xff1b;編碼保持默認&#xff08;ANSI …

ORDER BY子句在一個 SQL 查詢中只能出現一次

order by A.create_time,A.update_time desc和 order by A.create_time desc,A.update_time desc有區別嗎&#xff1f; 關鍵區別 第一個排序中 create_time 是升序(默認是ASC)&#xff0c;第二個是降序(DESC) 只有在 DESC 關鍵字緊跟在列名后面時&#xff0c;該列才會按降序排…

02-BTC-密碼學原理 對hash算法如果出現漏洞的思考

如果比特幣中某個哈希函數的抗碰撞性出現了漏洞怎么辦&#xff0c;怎么補救&#xff1f; 答&#xff1a;&#xff08;1&#xff09;攻擊場景&#xff1a; 偽造交易&#xff1a;攻擊者可構造兩個不同的交易&#xff08;如正常交易和惡意雙花交易&#xff09;具有相同的TxID&…

特征分解:線性代數在AI大模型中的核心工具

?? 博主簡介:CSDN博客專家、CSDN平臺優質創作者,高級開發工程師,數學專業,10年以上C/C++, C#, Java等多種編程語言開發經驗,擁有高級工程師證書;擅長C/C++、C#等開發語言,熟悉Java常用開發技術,能熟練應用常用數據庫SQL server,Oracle,mysql,postgresql等進行開發應用…