【 <二> 丹方改良:Spring 時代的 JavaWeb】之 Spring Boot 中的異常處理:全局異常與自定義異常

?<前文回顧>

點擊此處查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshare=blogcolumn&sharetype=blogcolumn&sharerId=12907601&sharerefer=PC&sharesource=FoyoDesigner&sharefrom=from_link

<今日更新>

一、開篇整活兒

今兒個咱嘮嘮 Spring Boot 里頭的異常處理。這玩意兒吧,說大不大,說小不小,整好了是錦上添花,整不好就是火上澆油。你要是剛入門,那可得悠著點兒,別一上來就整得自己“翻車”了。

二、Java 中的異常是啥構型?

Java 里頭的異常,說白了就是程序運行時出的岔子。Java 的異常體系是“樹形結構”,最頂上是?Throwable,往下分成?Error?和?Exception。Error?是那種嚴重的、沒法兒處理的錯誤,比如說內存溢出啥的。Exception?是那種可以處理的異常,比如說空指針、數組越界啥的。

1.?Exception?的分類

Exception?又分成兩種:受檢異常非受檢異常

  • 受檢異常:這種異常你得在代碼里頭顯式處理,要么?try-catch,要么?throws。比如說?IOException,你要是讀寫文件,那得處理這個異常。
  • 非受檢異常:這種異常不用顯式處理,比如說?NullPointerException、ArrayIndexOutOfBoundsException,這些異常通常是代碼寫得不嚴謹導致的。

Java Code

// 受檢異常示例

try {

????FileInputStream fis = new FileInputStream("file.txt");

} catch (IOException e) {

????e.printStackTrace();

}

// 非受檢異常示例

String str = null;

System.out.println(str.length()); // 這里會拋出 NullPointerException

2. 異常之間的關系

Java 里頭的異常是“繼承關系”,子類異常可以捕獲父類異常。比如說,IOException?是?Exception?的子類,你要是?catch?了?Exception,那?IOException?也能被捕獲。

Java Code

try {

????// 一些可能拋出異常的代碼

} catch (IOException e) {

????// 處理 IOException

} catch (Exception e) {

????// 處理其他 Exception

}

這段代碼里頭,IOException?會被第一個?catch?捕獲,其他的?Exception?會被第二個?catch?捕獲。

三、Spring Boot 中的全局異常處理

Spring Boot 里頭有個?@ControllerAdvice?注解,專門用來做全局異常處理。你可以把它想象成一個“兜底的”,Controller 里頭沒處理的異常,它都能接住。

1. 全局異常處理示例

Java Code

@ControllerAdvice

public class GlobalExceptionHandler {

????@ExceptionHandler(Exception.class)

????public ResponseEntity<String> handleException(Exception e) {

????????return new ResponseEntity<>("出錯了:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);

????}

}

這段代碼里頭,@ControllerAdvice?是用來定義一個全局的異常處理類,@ExceptionHandler?是用來處理特定類型的異常的。ResponseEntity?是用來返回 HTTP 響應的,里頭可以帶上狀態碼和響應體。

2. 處理特定異常

你可以針對不同的異常,寫不同的處理方法。比如說,處理?NullPointerException?和?IllegalArgumentException。

Java Code

@ControllerAdvice

public class GlobalExceptionHandler {

????@ExceptionHandler(NullPointerException.class)

????public ResponseEntity<String> handleNullPointerException(NullPointerException e) {

????????return new ResponseEntity<>("空指針異常:" + e.getMessage(), HttpStatus.BAD_REQUEST);

????}

????@ExceptionHandler(IllegalArgumentException.class)

????public ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException e) {

????????return new ResponseEntity<>("參數不合法:" + e.getMessage(), HttpStatus.BAD_REQUEST);

????}

}

這段代碼里頭,NullPointerException?和?IllegalArgumentException?會被分別處理,返回不同的錯誤信息。

四、自定義異常

有時候,Java 自帶的異常不夠用,你得自己整一個。自定義異常很簡單,繼承?Exception?或者?RuntimeException?就行。

1. 自定義異常示例

Java Code

public class MyCustomException extends RuntimeException {

????public MyCustomException(String message) {

????????super(message);

????}

}

這段代碼里頭,MyCustomException?是自定義異常,繼承自?RuntimeException,所以它是非受檢異常。

2. 使用自定義異常

你可以在代碼里頭拋出這個自定義異常。

Java Code

@RestController

@RequestMapping("/api")

public class MyController {

????@GetMapping("/test")

????public String test() {

????????throw new MyCustomException("這是我的自定義異常");

????}

}

這段代碼里頭,test?方法會拋出?MyCustomException,然后被全局異常處理器捕獲。

3. 處理自定義異常

你可以在全局異常處理器里頭,專門處理這個自定義異常。

Java Code

@ControllerAdvice

public class GlobalExceptionHandler {

????@ExceptionHandler(MyCustomException.class)

????public ResponseEntity<String> handleMyCustomException(MyCustomException e) {

????????return new ResponseEntity<>("自定義異常:" + e.getMessage(), HttpStatus.BAD_REQUEST);

????}

}

這段代碼里頭,MyCustomException?會被專門處理,返回自定義的錯誤信息。

五、異常的 AOP 處理

AOP(面向切面編程)是 Spring 里頭的一個高級特性,可以用來在方法執行前后做一些額外的事情。異常處理也可以用 AOP 來做。

1. AOP 處理異常示例

Java Code

@Aspect

@Component

public class ExceptionAspect {

????@AfterThrowing(pointcut = "execution(* com.example.demo.controller.*.*(..))", throwing = "e")

????public void handleException(Exception e) {

????????System.out.println("捕獲到異常:" + e.getMessage());

????}

}

這段代碼里頭,@Aspect?是用來定義一個切面,@AfterThrowing?是用來在方法拋出異常后執行的。pointcut?是指定哪些方法需要被切面處理,throwing?是指定異常對象的變量名。

2. AOP 和全局異常處理的區別

AOP 和全局異常處理都可以用來處理異常,但它們的應用場景不一樣。全局異常處理是用來處理 Controller 里頭的異常,而 AOP 可以用來處理任何地方的異常,比如說 Service 層、DAO 層啥的。

六、Spring Boot 里頭的異常處理坑點

1. 異常處理的順序

Spring Boot 里頭,異常處理的順序很重要。你要是先?catch?了?Exception,那后面的?catch?就不起作用了。

Java Code

@ControllerAdvice

public class GlobalExceptionHandler {

????@ExceptionHandler(Exception.class)

????public ResponseEntity<String> handleException(Exception e) {

????????return new ResponseEntity<>("出錯了:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);

????}

????@ExceptionHandler(NullPointerException.class)

????public ResponseEntity<String> handleNullPointerException(NullPointerException e) {

????????return new ResponseEntity<>("空指針異常:" + e.getMessage(), HttpStatus.BAD_REQUEST);

????}

}

這段代碼里頭,NullPointerException?會被?handleException?捕獲,handleNullPointerException?就不起作用了。

2. 異常信息的暴露

Spring Boot 里頭,默認會把異常信息返回給客戶端。你要是覺得這樣不安全,可以把異常信息隱藏掉。

Java Code

@ControllerAdvice

public class GlobalExceptionHandler {

????@ExceptionHandler(Exception.class)

????public ResponseEntity<String> handleException(Exception e) {

????????return new ResponseEntity<>("出錯了", HttpStatus.INTERNAL_SERVER_ERROR);

????}

}

這段代碼里頭,異常信息被隱藏了,客戶端只能看到“出錯了”。

3. 日志記錄

異常處理里頭,日志記錄是個大事兒。你要是沒記日志,那出了問題就抓瞎了。

Java Code

@ControllerAdvice

public class GlobalExceptionHandler {

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

????@ExceptionHandler(Exception.class)

????public ResponseEntity<String> handleException(Exception e) {

????????logger.error("捕獲到異常:", e);

????????return new ResponseEntity<>("出錯了", HttpStatus.INTERNAL_SERVER_ERROR);

????}

}

這段代碼里頭,異常信息被記錄到日志里頭了,方便以后排查問題。

專有名詞解釋

  1. Throwable:Java 中所有錯誤和異常的基類。
  2. Error:Java 中表示嚴重錯誤的類,通常無法恢復。
  3. Exception:Java 中表示可恢復異常的類。
  4. 受檢異常:必須在代碼中顯式處理的異常。
  5. 非受檢異常:不需要顯式處理的異常。
  6. ControllerAdvice:Spring 中用于定義全局異常處理類的注解。
  7. ExceptionHandler:Spring 中用于處理特定類型異常的注解。
  8. ResponseEntity:Spring 中用于封裝 HTTP 響應的類。
  9. AOP:面向切面編程,一種編程范式,用于在方法執行前后做一些額外的事情。
  10. Aspect:Spring 中用于定義切面的注解。
  11. AfterThrowing:Spring 中用于在方法拋出異常后執行的注解。
  12. Logger:用于記錄日志的工具類。

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

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

相關文章

思源配置阿里云 OSS 踩坑記

按照正常的配置IAM&#xff0c;賦予OSS權限&#xff0c;思源筆記還是無法使用&#xff0c;缺少ListBuckets權限。 正常配置權限&#xff0c;又無法覆蓋&#xff0c;因此需要手動配置權限。 {"Version": "1","Statement": [{"Effect":…

Debezium日常分享系列之:Debezium Charts

Debezium日常分享系列之&#xff1a;Debezium Charts 最近&#xff0c;圍繞 Debezium 圖表發生了一些變化&#xff0c;所以我在這里解釋這些變化是什么以及背后的理由。正如您從我們的最新公告中了解到的&#xff0c;我們將發布 Debezium 管理平臺的第一個版本。 Debezium 管理…

moveit2基礎教程上手-使用xarm6演示

0、前置信息 開發環境&#xff1a;wsl。 ros版本&#xff1a;jazzy&#xff0c;ubuntu版本&#xff1a;24.04 xarm-ros2地址 1、啟動Rviz&#xff0c;加載 Motion Planning Plugin&#xff0c;實現演示功能 Getting Started — MoveIt Documentation: Rolling documentation…

第十六屆藍橋杯模擬二

由硬件框圖可以知道我們要配置LED 和按鍵 一.LED 先配置LED的八個引腳為GPIO_OutPut,鎖存器PD2也是,然后都設置為起始高電平,生成代碼時還要去解決引腳沖突問題 二.按鍵 按鍵配置,由原理圖按鍵所對引腳要GPIO_Input 生成代碼,在文件夾中添加code文件夾,code中添加fun.…

在OpenGL ES中將值傳入shader的方法總結

在OpenGL ES中&#xff0c;將值傳入Shader的方式主要有以下幾種&#xff1a; 1. Uniform變量 用途&#xff1a;用于傳遞在繪制過程中不變的常量數據&#xff0c;如變換矩陣、顏色等。步驟&#xff1a; 在Shader中聲明Uniform變量&#xff1a;uniform mat4 uMVPMatrix; // 例如…

華為總部-華為東莞松山湖基地參觀游學攻略

你有聽說過全球科技巨頭-華為嗎&#xff1f;今天帶你深入了解這一世界標桿工廠的秘密基地。跟隨華研標桿游學服務商一窺華為的強大實力。 在東莞松山湖&#xff0c;這里不僅僅是華為的終端總部&#xff0c;更是研發、銷售和增值業務的核心區域。我們一行人抵達后&#xff0c;立…

Linux小知識

1. /etc目錄 我們在配置文件中一直會調用 /etc目錄 cd /etc/xxxx.conf etc的全稱是editable configuration&#xff08;其中一種說法&#xff09;意為可編輯的配置&#xff1b;此目錄主要用來存放系統的配置文件和初始化文件的&#xff1b;像網絡配置 用戶信息 各種服務的配置…

晶鑫股份邁向敏捷BI之路,永洪科技助力啟程

數據驅動的時代&#xff0c;每一次技術的創新和突破都在為企業的發展注入新的動力。而敏捷性也不再是選擇&#xff0c;是企業生存與發展的必要條件。作為連續5年獲得中國敏捷BI第一名的永洪科技&#xff0c;通過不斷地在數據技術領域深耕細作&#xff0c;再次迎來了行業內的關注…

基于CAMEL 的Workforce 實現多智能體協同工作系統

文章目錄 一、workforce 簡介1.架構設計2.通信機制 二、workforce 工作流程圖示例1.用戶角色2.工作流程 三、workforce 中重要函數說明1.__init__函數2.add_single_agent_worker 函數3.add_role_playing_worker 函數4.add_workforce 函數 四、基于workforce實現多智能體協調&am…

每日一題力扣2974.最小數字游戲c++

2974. 最小數字游戲 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:vector<int> numberGame(vector<int>& nums) {vector<int> arr(nums.size());sort(nums.begin(),nums.end());for(size_t i0;i<nums.size();i2){arr[i]nums[i1]…

對接馬來西亞、印度、韓國、越南等全球金融數據示例

Python對接StockTV全球金融數據API的封裝實現及使用教程&#xff1a; import requests import websockets import asyncio from typing import Dict, List, Optional, Union from datetime import datetimeclass StockTVClient:"""StockTV全球金融數據API客戶端…

Adobe After Effects 操作

Adobe After Effects &#xff08;AE&#xff09;可以實現將多個元素進行合成&#xff0c;實現特殊效果。AE的項目文件是aep&#xff0c;可以將素材、層、效果等一切信息&#xff0c;保存在這個項目文件中。 AE的原理&#xff0c;和PS的原理非常類似。 操作界面 操作界面如…

【React】基于自定義Hook提取公共邏輯

目錄 自定義Hook自定義Hook 1自定義Hook 2使用 注意事項 自定義Hook 作用&#xff1a;提取封裝一些公共的處理邏輯 玩法&#xff1a;創建一個函數&#xff0c;名字需要是 useXxx &#xff0c;后期就可以在組件中調用這個方法&#xff01; 自定義Hook 1 頁面加載的時候修改瀏…

AUTOSAR與arxml的文檔解析

如下是文檔腦圖 一、文檔概述 該文檔是 AUTOSAR 經典平臺的應用接口用戶指南&#xff0c;主要解釋 **Al Table&#xff08;應用接口表&#xff09;** 的結構、方法論及相關技術細節&#xff0c;幫助開發者理解如何通過標準化接口實現軟件組件的互操作性。 關鍵內容 目的&#…

油候插件、idea、VsCode插件推薦(自用)

開發軟件&#xff1a; 之前的文章&#xff1a; 開發必裝最實用工具軟件與網站 推薦一下我使用的開發工具 目前在用的 油候插件 AC-baidu-重定向優化百度搜狗谷歌必應搜索_favicon_雙列 讓查詢變成多列&#xff0c;而且可以流式翻頁 Github 增強 - 高速下載 github下載 TimerHo…

阿里云平臺服務器操作以及發布靜態項目

目錄&#xff1a; 1、云服務器介紹2、云服務器界面3、發布靜態項目1、啟動nginx2、ngixn訪問3、外網訪問測試4、拷貝靜態資源到nginx目錄下并重啟nginx 1、云服務器介紹 2、云服務器界面 實例詳情&#xff1a;里面主要顯示云服務的內外網地址以及一些啟動/停止的操作。監控&…

Spring Cache 實戰指南

redis中常見的問題 前言 在本文中&#xff0c;我們將探討 Redis 在緩存中的應用&#xff0c;并解決一些常見的緩存問題。為了簡化理解&#xff0c;本文中的一些配置是直接寫死的&#xff0c;實際項目中建議將這些配置寫入配置文件&#xff0c;并通過配置文件讀取。 一、為什…

區塊鏈開發技術公司:引領數字經濟的創新力量

在數字化浪潮席卷全球的今天&#xff0c;區塊鏈技術作為新興技術的代表&#xff0c;正以其獨特的去中心化、不可篡改和透明性等特點&#xff0c;深刻改變著各行各業的發展格局。區塊鏈開發技術公司&#xff0c;作為這一領域的先鋒和推動者&#xff0c;正不斷研發創新&#xff0…

EJS緩存解決多頁面相同閃動問題

基于 EJS 的模板引擎特性及其緩存機制&#xff0c;以下是關于緩存相同模塊的詳細解答&#xff1a; 一、EJS 緩存機制的核心能力 模板編譯緩存 EJS 默認會將編譯后的模板函數緩存在內存中&#xff0c;當相同模板文件被多次渲染時&#xff0c;會直接復用已編譯的模板函數&#x…

多條件排序(C# and Lua)

C# 升序排序 OrderBy 按升序對序列的元素進行排序 ThenBy 按升序對序列中的元素執行后續排序 降序排序 OrderByDescending 按降序對序列的元素排序 ThenByDescending 按降序對序列中的元素執行后續排序 public class Fruit {public int id;public string name;publi…