Spring Boot 2.X(十一):全局異常處理

前言

在 Java Web 系統(tǒng)開發(fā)中景描,不管是 Controller 層、Service 層還是 Dao 層赃春,都有可能拋出異常静秆。如果在每個方法中加上各種 try catch 的異常處理代碼牵素,那樣會使代碼非常繁瑣严衬。在Spring MVC 中,我們可以將所有類型的異常處理從各個單獨的方法中解耦出來笆呆,進行異常信息的統(tǒng)一處理和維護请琳。

在 Spring MVC 中全局異常捕獲處理的解決方案通常有兩種方式:

1.使用 @ControllerAdvice + @ExceptionHandler 注解進行全局的 Controller 層異常處理。

2.實現(xiàn) org.springframework.webb.servlet.HandlerExceptionResolver 接口中的 resolveException 方法赠幕。

使用 @ControllerAdvice + @ExceptionHandler 注解

1.定義統(tǒng)一異常處理類

@ControllerAdvice
public class GlobalExceptionHandler {

    private Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) {
        log.error("ExceptionHandler ===>" + e.getMessage());
        e.printStackTrace();
        // 這里可根據(jù)不同異常引起的類做不同處理方式
        String exceptionName = ClassUtils.getShortName(e.getClass());
        log.error("ExceptionHandler ===>" + exceptionName);
        ModelAndView mav = new ModelAndView();
        mav.addObject("stackTrace", e.getStackTrace());
        mav.addObject("errorMessage", e.getMessage());
        mav.addObject("url", req.getRequestURL());
        mav.setViewName("forward:/error/500");
        return mav;
    }
}

其中 @ExceptionHandler(value = Exception.class) 中的捕獲異常 value 可以自定義俄精,如下:

類型 描述
NullPointerException 當應用程序試圖訪問空對象時,則拋出該異常
SQLException 提供關于數(shù)據(jù)庫訪問錯誤或其他錯誤信息的異常
IndexOutOfBoundsException 指示某排序索引(例如對數(shù)組榕堰、字符串或向量的排序)超出范圍時拋出
NumberFormatException 當應用程序試圖將字符串轉換成一種數(shù)值類型竖慧,但該字符串不能轉換為適當格式時,拋出該異常
FileNotFoundException 當試圖打開指定路徑名表示的文件失敗時逆屡,拋出此異常
IOException 當發(fā)生某種I/O異常時圾旨,拋出此異常。此類是失敗或中斷的I/O操作生成的異常的通用類
ClassCastException 當試圖將對象強制轉換為不是實例的子類時康二,拋出該異常
ArrayStoreException 試圖將錯誤類型的對象存儲到一個對象數(shù)組時拋出的異常
IllegalArgumentException 拋出的異常表明向方法傳遞了一個不合法或不正確的參數(shù)
ArithmeticException 當出現(xiàn)異常的運算條件時碳胳,拋出此異常勇蝙。例如沫勿,一個整數(shù)“除以零”時挨约,拋出此類的一個實例
NegativeArraySizeException 如果應用程序試圖創(chuàng)建大小為負的數(shù)組,則拋出該異常
NoSuchMethodException 無法找到某一特定方法時产雹,拋出該異常
SecurityException 由安全管理器拋出的異常诫惭,指示存在安全侵犯
UnsupportedOperationException 當不支持請求的操作時,拋出該異常
RuntimeException 是那些可能在Java虛擬機正常運行期間拋出的異常的超類

當捕獲到響應的異常類型時蔓挖,會進入 defaultErrorHandler() 方法中的邏輯:把異常信息放入 model夕土,跳轉至 /error/500 請求URL。

2.異常信息展現(xiàn)

視圖控制器配置

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {

    /**
     * 視圖控制器配置
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {   
        registry.addViewController("/").setViewName("/index");//設置默認跳轉視圖為 /index
        registry.addViewController("/error/500").setViewName("/error/500");
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
        super.addViewControllers(registry);
        
    }
    
}

視圖模板

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Exception</h1>
<h3 th:text="${url}"></h3>
<h3 th:text="${errorMessage}"></h3>
<p  th:each="line : ${stackTrace}" th:text="${line}">  </p>
</body>
</html>

3.測試異常類

@Controller
public class TestController {

    @GetMapping("/index")
    public String hello() {
        int x = 1 / 0;
        return "hello";
    }
}

4.運行測試

瀏覽器訪問:http://127.0.0.1:8080/index

image

@ControllerAdvice 還能結合 @ModelAttribute 瘟判、@InitBinder 注解一起使用怨绣,實現(xiàn)全局數(shù)據(jù)綁定和全局數(shù)據(jù)預處理等功能。

實現(xiàn) HandlerExceptionResolver 接口

1.定義統(tǒng)一異常處理類

@Component
public class GlobalHandlerExceptionResolver implements HandlerExceptionResolver {

    private Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
            Exception ex) {
        Exception e = new Exception();
        //處理 UndeclaredThrowableException
        if (ex instanceof UndeclaredThrowableException) {
            e = (Exception) ((UndeclaredThrowableException) ex).getUndeclaredThrowable();
        } else {
            e = ex;
        }
        e.printStackTrace();
        //這里可以根據(jù)不同異常引起的類做不同處理方式
        String exceptionName = ClassUtils.getShortName(e.getClass());
        if(exceptionName.equals("ArrayIndexOutOfBoundsException")) {
            log.error("GlobalHandlerExceptionResolver resolveException ===>" + exceptionName);
            ModelAndView mav = new ModelAndView();
            mav.addObject("stackTrace", e.getStackTrace());
            mav.addObject("exceptionName", exceptionName);
            mav.addObject("errorMessage", e.getMessage());
            mav.addObject("url", request.getRequestURL());
            mav.setViewName("forward:/error/500");
            return mav;
        }
        return null;
    }

}

UndeclaredThrowableException 異常通常是在 RPC 接口調用場景或者使用 JDK 動態(tài)代理的場景時發(fā)生拷获。如果不預先處理轉換篮撑,測試捕獲到的異常則為 UndeclaredThrowableException,而不是真實的異常對象匆瓜。

2.異常信息展現(xiàn) 同上

3.測試異常類

@Controller
public class TestController {

    @GetMapping("/test")
    public String test() {
        String[] ss = new String[] { "1", "2" };
        System.out.print(ss[2]);
        return "hello";
    }

}

4.測試運行

測試前先把 @ControllerAdvice 注釋了赢笨。
瀏覽器訪問:http://127.0.0.1:8080/test

image

示例代碼

github

碼云

非特殊說明,本文版權歸 朝霧輕寒 所有驮吱,轉載請注明出處.

原文標題:Spring Boot 2.X(十一):全局異常處理

原文地址: https://www.zwqh.top/article/info/20

如果文章對您有幫助茧妒,請掃碼關注下我的公眾號,文章持續(xù)更新中...

image
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末左冬,一起剝皮案震驚了整個濱河市桐筏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌又碌,老刑警劉巖九昧,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異毕匀,居然都是意外死亡铸鹰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門皂岔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹋笼,“玉大人,你說我怎么就攤上這事躁垛∑侍海” “怎么了?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵教馆,是天一觀的道長逊谋。 經常有香客問我,道長土铺,這世上最難降的妖魔是什么胶滋? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任板鬓,我火速辦了婚禮,結果婚禮上究恤,老公的妹妹穿的比我還像新娘俭令。我一直安慰自己,他們只是感情好部宿,可當我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布抄腔。 她就那樣靜靜地躺著,像睡著了一般理张。 火紅的嫁衣襯著肌膚如雪赫蛇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天雾叭,我揣著相機與錄音棍掐,去河邊找鬼。 笑死拷况,一個胖子當著我的面吹牛作煌,可吹牛的內容都是我干的。 我是一名探鬼主播赚瘦,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼粟誓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了起意?” 一聲冷哼從身側響起鹰服,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎揽咕,沒想到半個月后悲酷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡亲善,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年设易,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛹头。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡顿肺,死狀恐怖,靈堂內的尸體忽然破棺而出渣蜗,到底是詐尸還是另有隱情屠尊,我是刑警寧澤,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布耕拷,位于F島的核電站讼昆,受9級特大地震影響,放射性物質發(fā)生泄漏骚烧。R本人自食惡果不足惜浸赫,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一嫌吠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧掺炭,春花似錦、人聲如沸凭戴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽么夫。三九已至者冤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間档痪,已是汗流浹背涉枫。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留腐螟,地道東北人愿汰。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像乐纸,于是被迫代替她去往敵國和親衬廷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內容

  • SpringMVC的異常處理 Spring 統(tǒng)一異常處理有 3 種方式汽绢,分別為: 使用@ExceptionHand...
    Java耕耘者閱讀 1,777評論 0 0
  • 好吧 吗跋,昨天去了西塘。 今天就來寫一下 西塘攻略好啦宁昭! 在網上買的門票跌宛,網上的價格是70元,進景區(qū)可以用身份證刷积仗,...
    阿魚君閱讀 253評論 0 0
  • 曾幾何時寂曹,NBA變成了一個江湖入问。這里有刀光劍影中的快意恩仇,也有俠肝義膽中的恩怨糾葛稀颁。江湖中芬失,有人叱咤風云,成為萬...
    籃球行為大賞閱讀 467評論 5 7
  • 關于未來 我似乎有很多的不同的打算 但目的總是美好的 成為很棒很獨立的人 想考高級工程師 想做一名攝影師 還想做服...
    煜喬閱讀 429評論 0 0
  • 感恩9件事: 1.感恩孩子的感冒在名醫(yī)的對癥藥方調理下匾灶,媽媽的精心呵護下棱烂,癥狀消失,好轉起來阶女。 2.感恩商場的優(yōu)惠...
    Amanangel閱讀 36評論 0 1