測試開發專題:spring-boot統一異常捕獲

来源:https://www.cnblogs.com/zyjimmortalp/archive/2020/05/09/12858884.html
-Advertisement-
Play Games

java異常介紹 異常時相對於return的一種退出機制,可以由系統觸發,也可由程式通過throw語句觸發,異常可以通過try/catch語句進行捕獲並處理,如果沒有捕獲,則會導致程式退出並輸出異常棧信息,異常有不同的類型,所有異常類都有一個共同的父類Throwable,下麵我們先從Throwabl ...


java異常介紹

異常時相對於return的一種退出機制,可以由系統觸發,也可由程式通過throw語句觸發,異常可以通過try/catch語句進行捕獲並處理,如果沒有捕獲,則會導致程式退出並輸出異常棧信息,異常有不同的類型,所有異常類都有一個共同的父類Throwable,下麵我們先從Throwable開始介紹。

Throwable

Throwable是所有異常類的父類,有四個構造方法

public Throwable(Throwable cause)
public Throwable(String message, Throwable cause) 
public Throwable(String message)
public Throwable()

主要有兩個類,一個是message,表示異常的消息,一個是cause,表示觸發該異常的其他異常,異常可以形成一個異常鏈,上層的異常由底層到的異常觸發,cause表示底層異常。

異常體系

java定義了非常多的異常類,來表示各種類型的異常,下麵的圖示是部分的異常類:

image-20200508232051535

Throwable是所有異常類的基類,它有兩個子類:Error和Exception。

  • Error錯誤

操作系統或者虛擬機發生的錯誤,這個時候程式是跑不起來的,代碼是無法處理的,一般表示系統錯誤或者資源耗盡,由java系統自己處理,比如圖示中給出的:虛擬機錯誤、棧溢出、記憶體溢出等錯誤

  • Exception

表示應用程式錯誤,是可以通過代碼處理的,有兩大類:一類是受檢異常(checked exception),一類是非受檢異常(uncheck exception),也就是runtime異常,他兩的區別就在於java是如何對待他們的,受檢異常,java會要求強制進行處理,不然編譯時不通過的,對於非受檢異常則沒有這個強制性的要求。

解釋

該怎麼理解受檢異常和非受檢異常呢,我的理解就是做某件事的時候我們能夠順利的按照我們預期的做完,但是實際上呢可能會出現各種各樣的情況,這種可能出現的情況就把他稱之為異常,這種異常有的我們能處理,有的我們不能處理,能處理的就把它稱作為受檢異常,不能處理的稱作為非受檢異常。

比如說,客戶端發送一個請求,要查詢資料庫,那有可能找到有可能沒找到,沒找到的話,就應該拋出runtime異常,再比如要去讀取文件,文件可能是不存在的,那就應該拋出checked exception,這其實就是bug,我們應該去處理的。

怎麼理解呢,比如讀取文件,當文件不存在,發生異常,能處理麽,當然可以處理啊,怎麼處理,把文件路徑改成正確的不就行了。從某種意義上來說,checked異常是真正的bug

沒有辦法處理的情況,比如說用戶輸入ID為2,查詢記錄能找到,但是如果輸入2000就找不到了,這裡的找不到就是一種異常情況,就需要產生一個運行時異常也就是非受檢異常。

已知異常和未知異常

上面我們提到的受檢異常 unchecked exception和運行時異常 RuntimeException都是從java語法層面來說的,那從程式開發者的角度來說,分為兩類:已知異常和未知異常。

已知異常和未知異常,其實就在於我們程式員是否主動的去處理異常。

  • 未知異常:當代碼中未對一些情況做出處理而引發的異常,這就是未知異常,一般這種異常都是因為服務端的代碼寫的有問題的,對於前段開發或者用戶,都是無意義的,記錄日誌供自己查看就行了。
  • 已知異常:更多的時候表示的是一種消息,用來提示用戶的輸入是否有問題,只不過這裡我們用異常的形式來處理,當然也可以通過其他方式處理,比如當做結果去返回,也是可以的,但是這種方式不如全部都看做異常,通過全局的異常處理器直接處理來的簡單。

Spring-Boot全局異常處理器

在使用spring-boot進行開發到的時候,有時我們需要對程式中拋出的異常進行統一的處理,spring-boot預留了響應的擴展點,我們只需要按照要求的方式去自定義自己的實現即可。

@ControllerAdvice
public class GlobalExceptionAdvice {

    @ExceptionHandler(value = Exception.class)
    public void handleHttpException(HttpServletRequest req, Exception ex){
  
    }
}

@ControllerAdvice表明GlobalExceptionAdvice是一個異常的處理類,具體的處理方法通過 @ExceptionHandler進行標記,通過value來指定能夠處理的異常類型。異常的處理方法需要傳入兩個參數,一個是HttpServletRequest請求對象,可以從這裡獲取請求相關的一些信息,比如請求的url或者參數等,另一個是Exception就是拋出的異常。

模擬異常發生

我們在異常的處理方法中列印一條語句

@ControllerAdvice
public class GlobalExceptionAdvice {

    @ExceptionHandler(value = Exception.class)
    public void handleHttpException(HttpServletRequest req, Exception ex){
        System.out.println("發生異常了");
    }
}

然後再Controller里拋出一個異常

@RestController
public class BannerController {

    @RequestMapping(value = "/v2/banner", method = {RequestMethod.GET})
    public String test() throws Exception {
        throw new Exception("我拋出來的");
    }
}

啟動程式後在瀏覽器中訪問路由,可以看到在控制臺中列印出了預期的信息

image-20200509001215452

當然在實際開發中,我們可能要多異常進行區分,該拋出什麼類型的異常,異常處理函數可也不只一個,還要對返回的異常信息進行自定義。

自定義異常類

當我們需要自定義異常類的時候,是該繼承自exception呢,還是繼承RuntimeException?下麵我們就來討論一下。

當用戶訪問一個不存在的資源的時候,很明顯這種情況我們是處理不了的,而且這種情況我們是可以判斷出來的,所以這裡應該使用Runtime異常。

image-20200509100041018

HttpException是所有自定義運行時異常類的基類,這裡定義兩個狀態碼,一個code是我們業務層面的定義,一個httpStatusCode是http請求的,資源不存在的異常定義為 NotFoundException

image-20200509100342221

在controller裡面拋出這個異常,

image-20200509103228206

那之前定義的 GlobalExceptionAdvice能夠監聽到這個異常呢?

當然能,NotFoundExceptionHttpException的子類,HttpExceptionRuntimeException的子類,RuntimeException又是 Exception的子類,@ExceptionHandler(value = Exception.class)全局異常處理器里指定的能夠處理的異常類是 Exception自然也能處理 NotFoundException

但是這裡也有不同的地方,我們自定義的 HttpException是多了兩個擴展欄位的,codehttpStatusCode,所以在全局異常處理器里需要對異常的類型進行判斷,如果是自定義的就需要添加這兩個欄位。

這裡呢有兩種方式進行處理:一種是在之前的異常處理方法裡面,進行類型判斷,另一種呢是可以再添加一個異常處理方法,專門處理自定義異常類

image-20200509104418301

這裡我們可以考慮一下,當我們拋出 NotFoundException異常的時候,是會進入哪一個異常處理方法里?還是說兩個都進呢?

我們可以來試驗一下,啟動程式後,看看在控制台列印的是什麼

image-20200509165843525

在瀏覽器里訪問路由以後,控制台顯示了handleHttpException異常處理方法里到的列印語句輸出的內容。

可以看到多個異常處理方法時可以同時存在的,各自處理自己所能處理的異常類。

下篇文章,我們來探討一下,如何自定義異常的返回信息,敬請關註,博客原文

歡迎大家去 我的博客 瞅瞅,裡面有更多關於測試實戰的內容哦!!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.關鍵字transient 1)一旦變數被transient修飾,變數將不再是對象持久化的一部分,該變數內容在序列化後無法獲得訪問。 2)transient關鍵字只能修飾變數,而不能修飾方法和類。註意,本地變數是不能被transient關鍵字修飾的。變數如果是用戶自定義類變數,則該類需要實現Ser ...
  • Spring框架是一個為Java應用程式的開發提供了綜合、廣泛的基礎性支持的Java平臺。Spring幫助開發者解決了開發中基礎性的問題,使得開發人員可以專註於應用程式的開發。 近兩年來,許多大廠在面試中都會頻繁問到Spring相關,記得第一次去阿裡面試時,可以說是慘遭“虐待”,被面試官逼問得啞口無 ...
  • 1.運算符的分類 1.算術運算符:+(加法)、-(減法)、*(乘法)、/(除法)、%(取模/取餘)、++(自增)、--(自減) 2.賦值運算符:=(賦值)、+=(加等)、-=(減等)、*=(乘等)、/=(除等)、%=(模等/取餘等) 3.關係運算符:>(大於)、<(小於)、>=(大於等於)、<=(小 ...
  • 前言 記錄一下如何用python爬取app數據,本文以爬取抖音視頻app為例。 編程工具:pycharm app抓包工具:mitmproxy app自動化工具:appium 運行環境:windows10 思路: 假設已經配置好我們所需要的工具 1、使用mitmproxy對手機app抓包獲取我們想要的 ...
  • 一、MyBatis-Plus 1、簡介 MyBatis-Plus 是一個 Mybatis 增強版工具,在 MyBatis 上擴充了其他功能沒有改變其基本功能,為了簡化開發提交效率而存在。 官網文檔地址: https://mp.baomidou.com/guide/ MyBatis-Plus 特性: ...
  • eclipse4.15 增加了該功能 下麵是官方更新說明 谷歌翻譯 啟用方法 ...
  • 1、安裝第三方庫並引入 import CameraRoll from '@react-native-community/cameraroll'; import RNFS from 'react-native-fs'; Github參考鏈接:CameraRoll RNFS 2、添加許可權 <uses-p ...
  • swoole實現視頻彈幕效果 轉自:https://www.cnblogs.com/xinliangcoder/p/10800910.html ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...