淺談Spring Boot 異常處理篇
前言
先談?wù)劇爱惓L幚怼边@件事。下面有 2 份偽代碼,對(duì)比下:
// ① 基于 if/else 判斷 if(deletePage(page) == E_OK){ if(registry.deleteReference(page.name) == E_OK){ if(configKeys.deleteKey(page.name.makeKey()) == E_OK){ logger.log("page deleted"); }else{ logger.log("configKey not deleted"); } }else{ logger.log("deleteReference from registry failed"); } }else{ logger.log("delete failed"); return E_RROR; }
// ② 基于異常處理 try{ deletePage(page); registry.deleteReference(page.name); configKeys.deleteKey(page.name.makeKey()); }catch(Exception e){ logError(e); }
可以看出,如果使用異常替代返回錯(cuò)誤碼,錯(cuò)誤處理代碼就能從主路徑邏輯中分離出來,得到簡(jiǎn)化!
②中,基于異常處理的代碼真的好嗎?其實(shí)是丑陋不堪的,它搞亂了代碼結(jié)構(gòu),把錯(cuò)誤處理與正常流程混為一談。最好把 try 和 catch 代碼塊的主體部分抽離出來,形成另外的函數(shù)。
// ③ 優(yōu)雅的異常處理邏輯 public void delete(Page page){ try{ deletePageAndAllReferences(page); }catch(Exception e){ logError(e); } } private void deletePageAndAllReferences(Page page) throw Exception{ deletePage(page); registry.deleteReference(page.name); configKeys.deleteKey(page.name.makeKey()); } private void logError(Exception e){ logger.log(e.getMessage()); }
③中,函數(shù)各司其職,更易于理解和修改了。
總結(jié):使用異常而不是錯(cuò)誤碼,優(yōu)雅地使用異常!函數(shù)應(yīng)該只做一件事,處理錯(cuò)誤就是一件事。因此,處理錯(cuò)誤的函數(shù)不該做其他事!
在 Spring Boot 中處理異常
1、默認(rèn)的異常處理
例如 401,404,500,5XX 等異常,Spring Boot 默認(rèn)會(huì)跳轉(zhuǎn)到預(yù)配置的頁(yè)面,此處以 thymeleaf 模板引擎為例:
+ resources + templates + error - 401.html - 404.html - 500.html
只需在 resources/templates/error/ 路徑下添加對(duì)應(yīng)的html文件即可。
2、局部異常處理
局部異常一般處理業(yè)務(wù)邏輯出現(xiàn)的異常情況,在 Controller 下使用 @ExceptionHandler 注解來處理異常。舉個(gè)小例子:
先定義 ResponseBean 和 ExceptionEnum 兩個(gè)對(duì)象,輔助完成優(yōu)雅的代碼。
/** * 統(tǒng)一響應(yīng) * @author anoy */ public class ResponseBean<T> { private int code; private String message; private T data; public ResponseBean(){} public ResponseBean(ExceptionEnum exceptionEnum){ this.code = exceptionEnum.getCode(); this.message = exceptionEnum.getMessage(); } // 省略 setter/getter }
/** * 異常類型枚舉 * @author anoy */ public enum ExceptionEnum { GIRL_FRIEND_NOT_FOUND(100000, "girl friend not found"); private int code; private String message; ExceptionEnum(int code, String message){ this.code = code; this.message = message; } public int getCode() { return code; } public String getMessage() { return message; } }
今天七夕,寫個(gè) GirlFriendNotFoundException(很有同感,是不是?)
@Controller public class UserController { @RequestMapping("/friend/{id}") public String friend(@PathVariable("id") Long id) throws GirlFriendNotFoundException { if (id == 1L){ throw new GirlFriendNotFoundException(); } return "friend"; } @ExceptionHandler(GirlFriendNotFoundException.class) @ResponseBody public ResponseBean handleGirlFriendNotFound(GirlFriendNotFoundException exception){ loggerError(exception); return new ResponseBean(ExceptionEnum.GIRL_FRIEND_NOT_FOUND); } private void logError(Exception e){ logger.error(e.getMessage()); } }
3、全局異常處理
個(gè)人觀點(diǎn):全局異常應(yīng)該處理系統(tǒng)故障級(jí)別的問題,像參數(shù)校驗(yàn)這種類型的異常,應(yīng)該作為局部異常來處理,例如 Redis 連接斷開,無法請(qǐng)求數(shù)據(jù),這種異常就應(yīng)該當(dāng)做全局異常來處理,在異常處理的邏輯中,還應(yīng)該添加通知到開發(fā)人員的功能,方便開發(fā)人員及時(shí)處理錯(cuò)誤!
全局異常處理,使用 @ControllerAdvice
和 @ExceptionHandler
來配合。
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(RedisConnectionFailureException.class) public void handlerRedisConnectionFailureException(RedisConnectionFailureException exception){ logError(exception); noticeToDev(); } private void logError(Exception e){ logger.error(e.getMessage()); } private void noticeToDev(){ // 通知具體開發(fā)人員 } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于在Java中反轉(zhuǎn)數(shù)組的4種詳細(xì)方法
這篇文章主要介紹了關(guān)于在Java中反轉(zhuǎn)數(shù)組的4種詳細(xì)方法,數(shù)組是一個(gè)固定長(zhǎng)度的存儲(chǔ)相同數(shù)據(jù)類型的數(shù)據(jù)結(jié)構(gòu),數(shù)組中的元素被存儲(chǔ)在一段連續(xù)的內(nèi)存空間中,今天我們來學(xué)習(xí)一下如何反轉(zhuǎn)數(shù)組2023-05-05詳解Mybatis多參數(shù)傳遞入?yún)⑺姆N處理方式
這篇文章主要介紹了詳解Mybatis多參數(shù)傳遞入?yún)⑺姆N處理方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04Java中的引用和動(dòng)態(tài)代理的實(shí)現(xiàn)詳解
這篇文章主要介紹了Java中的引用和動(dòng)態(tài)代理的實(shí)現(xiàn)詳解,涉及Java中的引用類型,JVMGC的可達(dá)性分析,代理模式等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11使用log4j2打印mybatis的sql執(zhí)行日志方式
這篇文章主要介紹了使用log4j2打印mybatis的sql執(zhí)行日志方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09Spring源碼解析之循環(huán)依賴的實(shí)現(xiàn)流程
這篇文章主要介紹了Spring源碼解析之循環(huán)依賴的實(shí)現(xiàn)流程,文章基于Java的相關(guān)內(nèi)容展開循環(huán)依賴的實(shí)現(xiàn)流程,需要的小伙伴可以參考一下2022-07-07Spring Cloud Alibaba配置多環(huán)境管理詳解與實(shí)戰(zhàn)代碼
本文通過實(shí)際案例詳細(xì)介紹了springboot配置多環(huán)境管理的使用,以及基于nacos的配置多環(huán)境管理的實(shí)踐,在實(shí)際開發(fā)中,配置多環(huán)境管理是一個(gè)很難避開的問題,同時(shí)也是微服務(wù)治理中一個(gè)很重要的內(nèi)容,感興趣的朋友跟隨小編一起看看吧2024-06-06Java編程細(xì)節(jié)重構(gòu)之為什么if-else不是好代碼詳析
這篇文章主要給大家介紹了關(guān)于Java編程細(xì)節(jié)重構(gòu)之為什么if-else不是好代碼的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)些學(xué)習(xí)吧2018-09-09IDEA?2020.3最新永久激活碼(免費(fèi)激活到?2099?年,親測(cè)有效)
分享一下?IntelliJ?IDEA?2020.3.1?最新激活注冊(cè)碼,破解教程如下,可免費(fèi)激活至?2099?年,親測(cè)有效,本文給大家分享兩種方法,感興趣的朋友參考下吧2021-01-01