衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

關于SpringBoot如何優雅的全局異常處理

電子工程師 ? 來源:博客 ? 作者:虛無境 ? 2021-05-31 14:25 ? 次閱讀

SpringBoot全局異常準備說明:如果想直接獲取工程那么可以直接跳到底部,通過鏈接下載工程代碼。

開發準備

環境要求JDK:1.8SpringBoot:1.5.17.RELEASE

首先還是Maven的相關依賴:

《properties》

《project.build.sourceEncoding》UTF-8《/project.build.sourceEncoding》

java.version》1.8《/java.version》

《maven.compiler.source》1.8《/maven.compiler.source》

《maven.compiler.target》1.8《/maven.compiler.target》

《/properties》

《parent》

《groupId》org.springframework.boot《/groupId》

《artifactId》spring-boot-starter-parent《/artifactId》

《version》1.5.17.RELEASE《/version》

《relativePath /》

《/parent》

《dependencies》

《!-- Spring Boot Web 依賴 核心 --》

《dependency》

《groupId》org.springframework.boot《/groupId》

《artifactId》spring-boot-starter-web《/artifactId》

《/dependency》

《!-- Spring Boot Test 依賴 --》

《dependency》

《groupId》org.springframework.boot《/groupId》

《artifactId》spring-boot-starter-test《/artifactId》

《scope》test《/scope》

《/dependency》

《dependency》

《groupId》com.alibaba《/groupId》

《artifactId》fastjson《/artifactId》

《version》1.2.41《/version》

《/dependency》

《/dependencies》

配置文件這塊基本不需要更改,全局異常的處理只需在代碼中實現即可。

代碼編寫

SpringBoot的項目已經對有一定的異常處理了,但是對于我們開發者而言可能就不太合適了,因此我們需要對這些異常進行統一的捕獲并處理。SpringBoot中有一個ControllerAdvice的注解,使用該注解表示開啟了全局異常的捕獲,我們只需在自定義一個方法使用ExceptionHandler注解然后定義捕獲異常的類型即可對這些捕獲的異常進行統一的處理。

我們根據下面的這個示例來看該注解是如何使用吧。

示例代碼:

@ControllerAdvice

public class MyExceptionHandler {

@ExceptionHandler(value =Exception.class)

public String exceptionHandler(Exception e){

System.out.println(“未知異常!原因是:”+e);

return e.getMessage();

}

}

上述的示例中,我們對捕獲的異常進行簡單的二次處理,返回異常的信息,雖然這種能夠讓我們知道異常的原因,但是在很多的情況下來說,可能還是不夠人性化,不符合我們的要求。那么我們這里可以通過自定義的異常類以及枚舉類來實現我們想要的那種數據吧。

自定義基礎接口

首先定義一個基礎的接口類,自定義的錯誤描述枚舉類需實現該接口。代碼如下:

public interface BaseErrorInfoInterface {

/** 錯誤碼*/

String getResultCode();

/** 錯誤描述*/

String getResultMsg();

}

自定義枚舉類

然后我們這里在自定義一個枚舉類,并實現該接口。代碼如下:

public enum CommonEnum implements BaseErrorInfoInterface {

// 數據操作錯誤定義

SUCCESS(“200”, “成功!”),

BODY_NOT_MATCH(“400”,“請求的數據格式不符!”),

SIGNATURE_NOT_MATCH(“401”,“請求的數字簽名不匹配!”),

NOT_FOUND(“404”, “未找到該資源!”),

INTERNAL_SERVER_ERROR(“500”, “服務器內部錯誤!”),

SERVER_BUSY(“503”,“服務器正忙,請稍后再試!”)

;

/** 錯誤碼 */

private String resultCode;

/** 錯誤描述 */

private String resultMsg;

CommonEnum(String resultCode, String resultMsg) {

this.resultCode = resultCode;

this.resultMsg = resultMsg;

}

@Override

public String getResultCode() {

return resultCode;

}

@Override

public String getResultMsg() {

return resultMsg;

}

}

自定義異常類

然后我們在來自定義一個異常類,用于處理我們發生的業務異常。代碼如下:

public class BizException extends RuntimeException {

private static final long serialVersionUID = 1L;

/**

* 錯誤碼

*/

protected String errorCode;

/**

* 錯誤信息

*/

protected String errorMsg;

public BizException() {

super();

}

public BizException(BaseErrorInfoInterface errorInfoInterface) {

super(errorInfoInterface.getResultCode());

this.errorCode = errorInfoInterface.getResultCode();

this.errorMsg = errorInfoInterface.getResultMsg();

}

public BizException(BaseErrorInfoInterface errorInfoInterface, Throwable cause) {

super(errorInfoInterface.getResultCode(), cause);

this.errorCode = errorInfoInterface.getResultCode();

this.errorMsg = errorInfoInterface.getResultMsg();

}

public BizException(String errorMsg) {

super(errorMsg);

this.errorMsg = errorMsg;

}

public BizException(String errorCode, String errorMsg) {

super(errorCode);

this.errorCode = errorCode;

this.errorMsg = errorMsg;

}

public BizException(String errorCode, String errorMsg, Throwable cause) {

super(errorCode, cause);

this.errorCode = errorCode;

this.errorMsg = errorMsg;

}

public String getErrorCode() {

return errorCode;

}

public void setErrorCode(String errorCode) {

this.errorCode = errorCode;

}

public String getErrorMsg() {

return errorMsg;

}

public void setErrorMsg(String errorMsg) {

this.errorMsg = errorMsg;

}

public String getMessage() {

return errorMsg;

}

@Override

public Throwable fillInStackTrace() {

return this;

}

}

自定義數據格式

順便這里我們定義一下數據的傳輸格式。代碼如下:

public class ResultBody {

/**

* 響應代碼

*/

private String code;

/**

* 響應消息

*/

private String message;

/**

* 響應結果

*/

private Object result;

public ResultBody() {

}

public ResultBody(BaseErrorInfoInterface errorInfo) {

this.code = errorInfo.getResultCode();

this.message = errorInfo.getResultMsg();

}

public String getCode() {

return code;

}

public void setCode(String code) {

this.code = code;

}

public String getMessage() {

return message;

}

public void setMessage(String message) {

this.message = message;

}

public Object getResult() {

return result;

}

public void setResult(Object result) {

this.result = result;

}

/**

* 成功

*

* @return

*/

public static ResultBody success() {

return success(null);

}

/**

* 成功

* @param data

* @return

*/

public static ResultBody success(Object data) {

ResultBody rb = new ResultBody();

rb.setCode(CommonEnum.SUCCESS.getResultCode());

rb.setMessage(CommonEnum.SUCCESS.getResultMsg());

rb.setResult(data);

return rb;

}

/**

* 失敗

*/

public static ResultBody error(BaseErrorInfoInterface errorInfo) {

ResultBody rb = new ResultBody();

rb.setCode(errorInfo.getResultCode());

rb.setMessage(errorInfo.getResultMsg());

rb.setResult(null);

return rb;

}

/**

* 失敗

*/

public static ResultBody error(String code, String message) {

ResultBody rb = new ResultBody();

rb.setCode(code);

rb.setMessage(message);

rb.setResult(null);

return rb;

}

/**

* 失敗

*/

public static ResultBody error( String message) {

ResultBody rb = new ResultBody();

rb.setCode(“-1”);

rb.setMessage(message);

rb.setResult(null);

return rb;

}

@Override

public String toString() {

return JSONObject.toJSONString(this);

}

}

自定義全局異常處理類

最后我們在來編寫一個自定義全局異常處理的類。代碼如下:

@ControllerAdvice

public class GlobalExceptionHandler {

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

/**

* 處理自定義的業務異常

* @param req

* @param e

* @return

*/

@ExceptionHandler(value = BizException.class)

@ResponseBody

public ResultBody bizExceptionHandler(HttpServletRequest req, BizException e){

logger.error(“發生業務異常!原因是:{}”,e.getErrorMsg());

return ResultBody.error(e.getErrorCode(),e.getErrorMsg());

}

/**

* 處理空指針的異常

* @param req

* @param e

* @return

*/

@ExceptionHandler(value =NullPointerException.class)

@ResponseBody

public ResultBody exceptionHandler(HttpServletRequest req, NullPointerException e){

logger.error(“發生空指針異常!原因是:”,e);

return ResultBody.error(CommonEnum.BODY_NOT_MATCH);

}

/**

* 處理其他異常

* @param req

* @param e

* @return

*/

@ExceptionHandler(value =Exception.class)

@ResponseBody

public ResultBody exceptionHandler(HttpServletRequest req, Exception e){

logger.error(“未知異常!原因是:”,e);

return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);

}

}

因為這里我們只是用于做全局異常處理的功能實現以及測試,所以這里我們只需在添加一個實體類和一個控制層類即可。

實體類

又是萬能的用戶表 (^▽^)

代碼如下:

public class User implements Serializable{

private static final long serialVersionUID = 1L;

/** 編號 */

private int id;

/** 姓名 */

private String name;

/** 年齡 */

private int age;

public User(){

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String toString() {

return JSONObject.toJSONString(this);

}

}

Controller 控制層

控制層這邊也比較簡單,使用Restful風格實現的CRUD功能,不同的是這里我故意弄出了一些異常,好讓這些異常被捕獲到然后處理。這些異常中,有自定義的異常拋出,也有空指針的異常拋出,當然也有不可預知的異常拋出(這里我用類型轉換異常代替),那么我們在完成代碼編寫之后,看看這些異常是否能夠被捕獲處理成功吧!

代碼如下:

@RestController

@RequestMapping(value = “/api”)

public class UserRestController {

@PostMapping(“/user”)

public boolean insert(@RequestBody User user) {

System.out.println(“開始新增。。。”);

//如果姓名為空就手動拋出一個自定義的異常!

if(user.getName()==null){

throw new BizException(“-1”,“用戶姓名不能為空!”);

}

return true;

}

@PutMapping(“/user”)

public boolean update(@RequestBody User user) {

System.out.println(“開始更新。。。”);

//這里故意造成一個空指針的異常,并且不進行處理

String str=null;

str.equals(“111”);

return true;

}

@DeleteMapping(“/user”)

public boolean delete(@RequestBody User user) {

System.out.println(“開始刪除。。。”);

//這里故意造成一個異常,并且不進行處理

Integer.parseInt(“abc123”);

return true;

}

@GetMapping(“/user”)

public List《User》 findByUser(User user) {

System.out.println(“開始查詢。。。”);

List《User》 userList =new ArrayList《》();

User user2=new User();

user2.setId(1L);

user2.setName(“xuwujing”);

user2.setAge(18);

userList.add(user2);

return userList;

}

}

App 入口

和普通的SpringBoot項目基本一樣。

代碼如下:

@SpringBootApplication

public class App

{

public static void main( String[] args )

{

SpringApplication.run(App.class, args);

System.out.println(“程序正在運行。。。”);

}

}

功能測試

我們成功啟動該程序之后,使用Postman工具來進行接口測試。

首先進行查詢,查看程序正常運行是否ok,使用GET 方式進行請求。

GET http://localhost:8181/api/user

”返回參數為:

{“id”:1,“name”:“xuwujing”,“age”:18}

”示例圖:

7922d7ee-c1d5-11eb-9e57-12bb97331649.png

可以看到程序正常返回,并沒有因自定義的全局異常而影響。

然后我們再來測試下自定義的異常是否能夠被正確的捕獲并處理。

使用POST方式進行請求

POST http://localhost:8181/api/user

”Body參數為:

{“id”:1,“age”:18}

”返回參數為:

{“code”:“-1”,“message”:“用戶姓名不能為空!”,“result”:null}

”示例圖:

796e0dd6-c1d5-11eb-9e57-12bb97331649.png

可以看出將我們拋出的異常進行數據封裝,然后將異常返回出來。

然后我們再來測試下空指針異常是否能夠被正確的捕獲并處理。在自定義全局異常中,我們除了定義空指針的異常處理,也定義最高級別之一的Exception異常,那么這里發生了空指針異常之后,它是回優先使用哪一個呢?這里我們來測試下。

使用PUT方式進行請求。

PUT http://localhost:8181/api/user

”Body參數為:

{“id”:1,“age”:18}

”返回參數為:

{“code”:“400”,“message”:“請求的數據格式不符!”,“result”:null}

”示例圖:

79859b90-c1d5-11eb-9e57-12bb97331649.png

我們可以看到這里的的確是返回空指針的異常護理,可以得出全局異常處理優先處理子類的異常。

那么我們在來試試未指定其異常的處理,看該異常是否能夠被捕獲。

使用DELETE方式進行請求。

DELETE http://localhost:8181/api/user

”Body參數為:

{“id”:1}

”返回參數為:

{“code”:“500”,“message”:“服務器內部錯誤!”,“result”:null}

這里可以看到它使用了我們在自定義全局異常處理類中的Exception異常處理的方法。到這里,測試就結束了。順便再說一下,自義定全局異常處理除了可以處理上述的數據格式之外,也可以處理頁面的跳轉,只需在新增的異常方法的返回處理上填寫該跳轉的路徑并不使用ResponseBody 注解即可。

細心的同學也許發現了在GlobalExceptionHandler類中使用的是ControllerAdvice注解,而非RestControllerAdvice注解,如果是用的RestControllerAdvice注解,它會將數據自動轉換成JSON格式,這種于Controller和RestController類似,所以我們在使用全局異常處理的之后可以進行靈活的選擇處理。

其它關于SpringBoot優雅的全局異常處理的文章就講解到這里了,如有不妥,歡迎指正!

項目地址

SpringBoot全局異常的處理項目工程地址//github.com/xuwujing/springBoot-study/tree/master/springboot-exceptionHandler

編輯;jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 代碼
    +關注

    關注

    30

    文章

    4828

    瀏覽量

    69058
  • JDK
    JDK
    +關注

    關注

    0

    文章

    82

    瀏覽量

    16637
  • PUT
    PUT
    +關注

    關注

    0

    文章

    5

    瀏覽量

    6324
  • SpringBoot
    +關注

    關注

    0

    文章

    174

    瀏覽量

    201

原文標題:看看人家SpringBoot的全局異常處理多么優雅...

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    串口通訊異常處理方法 串口設備連接方式

    串口通信異常處理方法 1. 異常檢測 在串口通信中,首先需要能夠檢測到異常情況。異常檢測可以通過以下幾種方式實現: 硬件檢測 :利用串口硬件
    的頭像 發表于 12-27 09:53 ?704次閱讀

    socket編程中的錯誤處理技巧

    :錯誤處理能夠確保程序在遇到異常情況時不會崩潰,而是能夠優雅處理問題。 提升用戶體驗 :通過適當的錯誤處理,可以給用戶提供清晰的錯誤信息
    的頭像 發表于 11-01 17:47 ?950次閱讀

    ARM處理器的異常中斷響應過程

    ARM處理器的異常中斷響應是嵌入式系統設計中一個至關重要的環節,它確保了系統在面對內部或外部事件時能夠穩定、可靠地運行。
    的頭像 發表于 09-10 11:18 ?1146次閱讀

    TI C64x+ DSP內核異常處理機制的應用

    電子發燒友網站提供《TI C64x+ DSP內核異常處理機制的應用.pdf》資料免費下載
    發表于 08-28 11:54 ?0次下載
    TI C64x+ DSP內核<b class='flag-5'>異常</b><b class='flag-5'>處理</b>機制的應用

    Panasonic松下焊接電異常處理

    電子發燒友網站提供《Panasonic松下焊接電異常處理.pdf》資料免費下載
    發表于 08-19 14:24 ?0次下載

    嵌入式C編程常用的異常錯誤處理

    嵌入式C編程中,異常錯誤處理是確保系統穩定性和可靠性的重要部分。以下是一些常見的異常錯誤處理方法及其詳細說明和示例: 1. 斷言 (Assertions) 斷言用于在開發階段捕獲程
    發表于 08-06 14:32

    一站式統一返回值封裝、異常處理異常錯誤碼解決方案—最強的Sping Boot接口優雅響應處理

    1. 前言 統一返回值封裝、統一異常處理異常錯誤碼體系的意義在于提高代碼的可維護性和可讀性,使得代碼更加健壯和穩定。統一返回值封裝可以避免每一個接口都需要手工拼裝響應報文;統一異常
    的頭像 發表于 06-20 15:42 ?650次閱讀

    專業:出整套TP圖,抄板,調試,處理異常

    在觸摸屏行業工作多年,熟悉GF/GFF/GG結構與市場常用IC,手機/車載前裝后裝/工控/手表/商顯都做過 現承接所有關于觸摸屏項目評估,出圖以及觸摸屏調試,異常處理。歡迎各位同行聯系。 VX:yibai522
    發表于 05-30 12:01

    CYT2B7 SFlash被異常修改的原因?

    批次的; 比較奇怪的是,代碼中并沒有任何調用修改SFlash的API接口,僅有擦寫Code Flash和Work Flash代碼; 那有什么可能會導致芯片的SFlash區被異常修改呢?關于
    發表于 05-28 08:11

    全局變量太多有哪些弊端?

    隨著全局變量的增多,不同模塊的變量名可能會產生沖突或混淆,導致代碼難以理解和維護。同時,全局變量使得代碼中的依賴關系變得復雜,難以追蹤和理解。這增加了新開發人員的學習成本,也增加了修改和調試的難度。
    發表于 04-24 09:15 ?953次閱讀

    如何處理STM32的HAL庫函數返回異常問題?

    (1)官方提供的例程里面,例如返回的結果不是 HAL_OK 的結果,一般直接跳轉到 錯誤處理的函數里面了。這樣寫的目的是給開發者根據實際情況自己寫異常處理代碼。 (2)比較現實是,在項目中,如果
    發表于 04-17 06:39

    熔纖機放電異常怎么處理

    構成威脅。因此,我們需要及時發現和處理這種異常,以確保設備的正常運行和操作人員的安全。 首先,讓我們了解一下熔纖機的基本原理和構造。熔纖機主要由供料系統、加熱系統、熔融區、拉伸區和收卷區組成。供料系統將原材
    的頭像 發表于 04-08 16:13 ?1433次閱讀

    變壓器運行中常見的異常現象應如何處理呢?

    變壓器運行中常見的異常現象應如何處理
    的頭像 發表于 03-08 09:19 ?655次閱讀
    變壓器運行中常見的<b class='flag-5'>異常</b>現象應如何<b class='flag-5'>處理</b>呢?

    介紹C語言中錯誤處理異常處理的一些常用的方法和策略

    C語言是一種低級的、靜態的、結構化的編程語言,它沒有提供像C++或Java等高級語言中的異常處理機制,例如try-catch-finally等。
    的頭像 發表于 02-28 14:25 ?677次閱讀

    優雅停機是什么?SpringBoot+Nacos+k8s實現優雅停機

    優雅停機是什么?網上說的優雅下線、無損下線,都是一個意思。
    的頭像 發表于 02-20 10:00 ?2211次閱讀
    <b class='flag-5'>優雅</b>停機是什么?<b class='flag-5'>SpringBoot</b>+Nacos+k8s實現<b class='flag-5'>優雅</b>停機
    湖南省| 全讯网bbin888.com| 哪个百家乐官网投注平台信誉好| 免费百家乐分析工具| 怎样打百家乐官网的玩法技巧和规则 | 真人百家乐官网皇冠网| 百家乐游戏作弊| 百家乐官网包台| bet365备用器| 百家乐噢门棋牌| 现金百家乐官网赌法| 金煌棋牌官网| 百家乐官网真钱棋牌| 大发888下载不了| 百家乐能赢到钱吗| 百家乐官网开放词典新浪| 老虎机价格| 至尊百家乐奇热网| 百家乐官网赌博娱乐| e世博备用网址| 盛大百家乐的玩法技巧和规则| 百威百家乐官网的玩法技巧和规则 | 百家乐高命中投注| 百家乐官网赌场在线娱乐| 百家乐园百乐彩| 在线百家乐作弊| 百家乐怎样算大小| 百家乐官网智能分析| 宝马会娱乐城| 威尼斯人娱乐城代理| 博E百百家乐娱乐城| 百家乐官网欧洲赔率| 百家乐官网稳赚打法| 波克城市棋牌中心| 真人百家乐蓝盾赌场娱乐网规则| 百家乐经验之谈| 百家乐官网二十一点| 泷泽罗拉种子| 大发888最新版本下载| 真人百家乐园| 百家乐官网77scs官|