日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

SpringBoot的全局异常处理的优雅吃法!要进来学习下吗

發(fā)布時(shí)間:2025/3/19 javascript 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringBoot的全局异常处理的优雅吃法!要进来学习下吗 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

SpringBoot的全局異常處理的優(yōu)雅吃法!要進(jìn)來學(xué)習(xí)下嗎

SpringBoot全局異常準(zhǔn)備
開發(fā)準(zhǔn)備
環(huán)境要求 JDK :1.8 SpringBoot :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>

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

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

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

示例代碼:

@ControllerAdvice public class MyExceptionHandler {@ExceptionHandler(value =Exception.class)public String exceptionHandler(Exception e){System.out.println("未知異常!原因是:"+e);return e.getMessage();} }

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

自定義基礎(chǔ)接口類

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

public interface BaseErrorInfoInterface {/** 錯(cuò)誤碼*/String getResultCode();/** 錯(cuò)誤描述*/String getResultMsg(); }

自定義枚舉類

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

public enum CommonEnum implements BaseErrorInfoInterface {// 數(shù)據(jù)操作錯(cuò)誤定義SUCCESS("200", "成功!"), BODY_NOT_MATCH("400","請(qǐng)求的數(shù)據(jù)格式不符!"),SIGNATURE_NOT_MATCH("401","請(qǐng)求的數(shù)字簽名不匹配!"),NOT_FOUND("404", "未找到該資源!"), INTERNAL_SERVER_ERROR("500", "服務(wù)器內(nèi)部錯(cuò)誤!"),SERVER_BUSY("503","服務(wù)器正忙,請(qǐng)稍后再試!");/** 錯(cuò)誤碼 */private String resultCode;/** 錯(cuò)誤描述 */private String resultMsg;CommonEnum(String resultCode, String resultMsg) {this.resultCode = resultCode;this.resultMsg = resultMsg;}@Overridepublic String getResultCode() {return resultCode;}@Overridepublic String getResultMsg() {return resultMsg;}}

自定義異常類

然后我們?cè)趤碜远x一個(gè)異常類,用于處理我們發(fā)生的業(yè)務(wù)異常。 代碼如下:

public class BizException extends RuntimeException {private static final long serialVersionUID = 1L;/*** 錯(cuò)誤碼*/protected String errorCode;/*** 錯(cuò)誤信息*/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;}@Overridepublic 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;}@Overridepublic String toString() {return JSONObject.toJSONString(this);}}

自定義全局異常處理類

最后我們?cè)趤砭帉懸粋€(gè)自定義全局異常處理的類。 代碼如下:

@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)@ResponseBodypublic 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)@ResponseBodypublic ResultBody exceptionHandler(HttpServletRequest req, Exception e){logger.error("未知異常!原因是:",e);return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);} }

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

實(shí)體類

又是萬能的用戶表 ( ▽ )

代碼如下:

public class User implements Serializable{private static final long serialVersionUID = 1L;/** 編號(hào) */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 控制層

控制層這邊也比較簡(jiǎn)單,使用Restful風(fēng)格實(shí)現(xiàn)的CRUD功能,不同的是這里我故意弄出了一些異常,好讓這些異常被捕獲到然后處理。這些異常中,有自定義的異常拋出,也有空指針的異常拋出,當(dāng)然也有不可預(yù)知的異常拋出(這里我用類型轉(zhuǎn)換異常代替),那么我們?cè)谕瓿纱a編寫之后,看看這些異常是否能夠被捕獲處理成功吧!

代碼如下:

@RestController @RequestMapping(value = "/api") public class UserRestController {@PostMapping("/user")public boolean insert(@RequestBody User user) {System.out.println("開始新增...");//如果姓名為空就手動(dòng)拋出一個(gè)自定義的異常!if(user.getName()==null){throw new BizException("-1","用戶姓名不能為空!");}return true;}@PutMapping("/user")public boolean update(@RequestBody User user) {System.out.println("開始更新...");//這里故意造成一個(gè)空指針的異常,并且不進(jìn)行處理String str=null;str.equals("111");return true;}@DeleteMapping("/user")public boolean delete(@RequestBody User user) {System.out.println("開始刪除...");//這里故意造成一個(gè)異常,并且不進(jìn)行處理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項(xiàng)目基本一樣。

代碼如下:

@SpringBootApplication public class App {public static void main( String[] args ){SpringApplication.run(App.class, args);System.out.println("程序正在運(yùn)行...");} }

功能測(cè)試
我們成功啟動(dòng)該程序之后,使用Postman工具來進(jìn)行接口測(cè)試。

首先進(jìn)行查詢,查看程序正常運(yùn)行是否ok,使用GET 方式進(jìn)行請(qǐng)求。

“GET http://localhost:8181/api/user”返回參數(shù)為:{"id":1,"name":"xuwujing","age":18}

示例圖:

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

然后我們?cè)賮頊y(cè)試下自定義的異常是否能夠被正確的捕獲并處理。

使用POST方式進(jìn)行請(qǐng)求

“POST http://localhost:8181/api/user”Body參數(shù)為:{"id":1,"age":18}”返回參數(shù)為:{"code":"-1","message":"用戶姓名不能為空!","result":null}

示例圖:

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

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

使用PUT方式進(jìn)行請(qǐng)求。

“PUT http://localhost:8181/api/user”Body參數(shù)為:“{“id”:1,“age”:18}”返回參數(shù)為:“{“code”:“400”,“message”:“請(qǐng)求的數(shù)據(jù)格式不符!”,“result”:null}”

示例圖:

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

那么我們?cè)趤碓囋囄粗付ㄆ洚惓5奶幚?#xff0c;看該異常是否能夠被捕獲。

使用DELETE方式進(jìn)行請(qǐng)求。

“DELETE http://localhost:8181/api/user”Body參數(shù)為:“{“id”:1}”返回參數(shù)為:“{“code”:“500”,“message”:“服務(wù)器內(nèi)部錯(cuò)誤!”,“result”:null}”

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

細(xì)心的同學(xué)也許發(fā)現(xiàn)了在 GlobalExceptionHandler 類中使用的是 ControllerAdvice 注解,而非 RestControllerAdvice 注解,如果是用的 RestControllerAdvice 注解,它會(huì)將數(shù)據(jù)自動(dòng)轉(zhuǎn)換成JSON格式,這種于 Controller 和 RestController 類似,所以我們?cè)谑褂萌之惓L幚淼闹罂梢赃M(jìn)行靈活的選擇處理。

小結(jié)
關(guān)于SpringBoot優(yōu)雅的全局異常處理的方法,就到這里啦,有什么不懂的可在評(píng)論區(qū)交流,如有不妥,歡迎指正!

碼字不易 請(qǐng)大家給我點(diǎn)贊+關(guān)注+評(píng)論!一條龍

文章來源:https://www.jianshu.com/p/dc99ffc6117d

我是Remi醬~~

與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的SpringBoot的全局异常处理的优雅吃法!要进来学习下吗的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。