在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

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

3天內(nèi)不再提示

關(guān)于SpringBoot如何優(yōu)雅的全局異常處理

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

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

開發(fā)準(zhǔn)備

環(huán)境要求JDK:1.8SpringBoot:1.5.17.RELEASE

首先還是Maven的相關(guān)依賴:

《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》

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

代碼編寫

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

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

示例代碼:

@ControllerAdvice

public class MyExceptionHandler {

@ExceptionHandler(value =Exception.class)

public String exceptionHandler(Exception e){

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

return e.getMessage();

}

}

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

自定義基礎(chǔ)接口

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

public interface BaseErrorInfoInterface {

/** 錯誤碼*/

String getResultCode();

/** 錯誤描述*/

String getResultMsg();

}

自定義枚舉類

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

public enum CommonEnum implements BaseErrorInfoInterface {

// 數(shù)據(jù)操作錯誤定義

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

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

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

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

INTERNAL_SERVER_ERROR(“500”, “服務(wù)器內(nèi)部錯誤!”),

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

;

/** 錯誤碼 */

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;

}

}

自定義異常類

然后我們在來自定義一個異常類,用于處理我們發(fā)生的業(yè)務(wù)異常。代碼如下:

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;

}

}

自定義數(shù)據(jù)格式

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

public class ResultBody {

/**

* 響應(yīng)代碼

*/

private String code;

/**

* 響應(yīng)消息

*/

private String message;

/**

* 響應(yīng)結(jié)果

*/

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);

/**

* 處理自定義的業(yè)務(wù)異常

* @param req

* @param e

* @return

*/

@ExceptionHandler(value = BizException.class)

@ResponseBody

public ResultBody bizExceptionHandler(HttpServletRequest req, BizException e){

logger.error(“發(fā)生業(yè)務(wù)異常!原因是:{}”,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(“發(fā)生空指針異常!原因是:”,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);

}

}

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

實體類

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

代碼如下:

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風(fēng)格實現(xiàn)的CRUD功能,不同的是這里我故意弄出了一些異常,好讓這些異常被捕獲到然后處理。這些異常中,有自定義的異常拋出,也有空指針的異常拋出,當(dāng)然也有不可預(yù)知的異常拋出(這里我用類型轉(zhuǎn)換異常代替),那么我們在完成代碼編寫之后,看看這些異常是否能夠被捕獲處理成功吧!

代碼如下:

@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

”返回參數(shù)為:

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

”示例圖:

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

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

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

使用POST方式進行請求

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

”Body參數(shù)為:

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

”返回參數(shù)為:

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

”示例圖:

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

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

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

使用PUT方式進行請求。

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

”Body參數(shù)為:

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

”返回參數(shù)為:

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

”示例圖:

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

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

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

使用DELETE方式進行請求。

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

”Body參數(shù)為:

{“id”:1}

”返回參數(shù)為:

{“code”:“500”,“message”:“服務(wù)器內(nèi)部錯誤!”,“result”:null}

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

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

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

項目地址

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

編輯;jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4807

    瀏覽量

    68787
  • JDK
    JDK
    +關(guān)注

    關(guān)注

    0

    文章

    81

    瀏覽量

    16604
  • PUT
    PUT
    +關(guān)注

    關(guān)注

    0

    文章

    5

    瀏覽量

    6319
  • SpringBoot
    +關(guān)注

    關(guān)注

    0

    文章

    174

    瀏覽量

    187

原文標(biāo)題:看看人家SpringBoot的全局異常處理多么優(yōu)雅...

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

收藏 人收藏

    評論

    相關(guān)推薦

    串口通訊異常處理方法 串口設(shè)備連接方式

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

    socket編程中的錯誤處理技巧

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

    ARM處理器的異常中斷響應(yīng)過程

    ARM處理器的異常中斷響應(yīng)是嵌入式系統(tǒng)設(shè)計中一個至關(guān)重要的環(huán)節(jié),它確保了系統(tǒng)在面對內(nèi)部或外部事件時能夠穩(wěn)定、可靠地運行。
    的頭像 發(fā)表于 09-10 11:18 ?1076次閱讀

    TI C64x+ DSP內(nèi)核異常處理機制的應(yīng)用

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

    Panasonic松下焊接電異常處理

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

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

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

    一站式統(tǒng)一返回值封裝、異常處理異常錯誤碼解決方案—最強的Sping Boot接口優(yōu)雅響應(yīng)處理

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

    專業(yè):出整套TP圖,抄板,調(diào)試,處理異常

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

    CYT2B7 SFlash被異常修改的原因?

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

    熔纖機放電異常怎么處理

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

    變壓器運行中常見的異常現(xiàn)象應(yīng)如何處理呢?

    變壓器運行中常見的異常現(xiàn)象應(yīng)如何處理
    的頭像 發(fā)表于 03-08 09:19 ?627次閱讀
    變壓器運行中常見的<b class='flag-5'>異常</b>現(xiàn)象應(yīng)如何<b class='flag-5'>處理</b>呢?

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

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

    優(yōu)雅停機是什么?SpringBoot+Nacos+k8s實現(xiàn)優(yōu)雅停機

    優(yōu)雅停機是什么?網(wǎng)上說的優(yōu)雅下線、無損下線,都是一個意思。
    的頭像 發(fā)表于 02-20 10:00 ?2143次閱讀
    <b class='flag-5'>優(yōu)雅</b>停機是什么?<b class='flag-5'>SpringBoot</b>+Nacos+k8s實現(xiàn)<b class='flag-5'>優(yōu)雅</b>停機

    CAN模塊RxBuffer接收異常要怎么處理呢?

    Cy_CANFD_DeInit后再重新Init也沒用,那部分異常的CAN消息仍無法接收到。請問在這種情況下要怎么處理呢? 現(xiàn)象: 1、CAN模塊正常工作 2、其他中斷占用過多的CPU時間 3、CAN模塊異常,部分(放在
    發(fā)表于 02-01 08:10

    使用dsram和psram時Aurix Tricore TC277全局變量異常的原因?

    我的數(shù)學(xué)模型在 dsam 中有許多全局變量,ADS 會自動擴展并將這些變量放到 psram 中,但是 psram 的這些變量總是異常,例如下面的代碼部分,在這個模型中我必須得到 \" 1
    發(fā)表于 01-23 07:58
    主站蜘蛛池模板: 欧美精品xxxxbbbb| 欧美黑人性色黄在线视频| 国产图片综合| free欧美性| 视频在线观看h| 一级片a| 伊人黄色| 国产乱人视频免费播放| 国产精品视频一区二区三区| 久久久夜色精品国产噜噜| 色多视频| 欧美一级视频免费看| 免费高清特级毛片| 色爽爽爽爽爽爽爽爽| 在线www天堂资源网| 香蕉成人国产精品免费看网站| 日韩在线一区二区| 亚洲伊人久久大香线蕉综合图片| 四虎影院在线网址| 天堂bt资源在线官网| 一级毛片无毒不卡直接观看| 午夜免费成人| 欧美高清milf在线播放| 色黄网站成年女人色毛片 | 天天操天天干天天爽| 天天综合网久久| 国产手机视频在线| 99久久免费午夜国产精品| 国产精品午夜在线观看| 中文字幕在线一区二区在线| 黄色永久免费| h视频在线免费| 一区二区三区无码高清视频| 国产性videostv另类极品| 久久国产精品免费看| 中文字幕欧美成人免费| 深爱激情婷婷| 国产乱淫a∨片免费视频| 人人弄| 一区二区视频| 特级片网站|