1. 程式人生 > >Spring Boot 2.X(十一):全域性異常處理

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

前言

在 Java Web 系統開發中,不管是 Controller 層、Service 層還是 Dao 層,都有可能丟擲異常。如果在每個方法中加上各種 try catch 的異常處理程式碼,那樣會使程式碼非常繁瑣。在Spring MVC 中,我們可以將所有型別的異常處理從各個單獨的方法中解耦出來,進行異常資訊的統一處理和維護。

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

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

2.實現 org.springframework.webb.servlet.HandlerExceptionResolver 介面中的 resolveException 方法。

使用 @ControllerAdvice + @ExceptionHandler 註解

1.定義統一異常處理類

@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();
        // 這裡可根據不同異常引起的類做不同處理方式
        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 提供關於資料庫訪問錯誤或其他錯誤資訊的異常
IndexOutOfBoundsException 指示某排序索引(例如對陣列、字串或向量的排序)超出範圍時丟擲
NumberFormatException 當應用程式試圖將字串轉換成一種數值型別,但該字串不能轉換為適當格式時,丟擲該異常
FileNotFoundException 當試圖開啟指定路徑名錶示的檔案失敗時,丟擲此異常
IOException 當發生某種I/O異常時,丟擲此異常。此類是失敗或中斷的I/O操作生成的異常的通用類
ClassCastException 當試圖將物件強制轉換為不是例項的子類時,丟擲該異常
ArrayStoreException 試圖將錯誤型別的物件儲存到一個物件陣列時丟擲的異常
IllegalArgumentException 丟擲的異常表明向方法傳遞了一個不合法或不正確的引數
ArithmeticException 當出現異常的運算條件時,丟擲此異常。例如,一個整數“除以零”時,丟擲此類的一個例項
NegativeArraySizeException 如果應用程式試圖建立大小為負的陣列,則丟擲該異常
NoSuchMethodException 無法找到某一特定方法時,丟擲該異常
SecurityException 由安全管理器丟擲的異常,指示存在安全侵犯
UnsupportedOperationException 當不支援請求的操作時,丟擲該異常
RuntimeException 是那些可能在Java虛擬機器正常執行期間丟擲的異常的超類

當捕獲到響應的異常型別時,會進入 defaultErrorHandler() 方法中的邏輯:把異常資訊放入 model,跳轉至 /error/500 請求URL。

2.異常資訊展現

檢視控制器配置

@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

@ControllerAdvice 還能結合 @ModelAttribute 、@InitBinder 註解一起使用,實現全域性資料繫結和全域性資料預處理等功能。

實現 HandlerExceptionResolver 介面

1.定義統一異常處理類

@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();
        //這裡可以根據不同異常引起的類做不同處理方式
        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 動態代理的場景時發生。如果不預先處理轉換,測試捕獲到的異常則為 UndeclaredThrowableException,而不是真實的異常物件。

2.異常資訊展現 同上

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

示例程式碼

github

碼雲

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

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

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

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

相關推薦

Spring Boot 2.X()全域性異常處理

前言 在 Java Web 系統開發中,不管是 Controller 層、Service 層還是 Dao 層,都有可能丟擲異常。如果在每個方法中加上各種 try catch 的異常處理程式碼,那樣會使程式碼非常繁瑣。在Spring MVC 中,我們可以將所有型別的異常處理從各個單獨的方法中解耦出來,進行異常資

Spring Boot 2.X(二)定時任務

簡介 定時任務是後端開發中常見的需求,主要應用場景有定期資料報表、定時訊息通知、非同步的後臺業務邏輯處理、日誌分析處理、垃圾資料清理、定時更新快取等等。 Spring Boot 集成了一整套的定時任務工具,讓我們專注於完成邏輯,剩下的基礎排程工作將自動完成。 通用實現方式 實現方式 描述 jav

Spring Boot 2.X(四)日誌功能 Logback

Logback 簡介 Logback 是由 SLF4J 作者開發的新一代日誌框架,用於替代 log4j。 主要特點是效率更高,架構設計夠通用,適用於不同的環境。 Logback 分為三個模組:logback-core,logback-classic和logback-access。 logback-core 模

Spring Boot 2.X(五)整合 Swagger2 開發 API 文件(線上+離線)

前言 相信很多後端開發在專案中都會碰到要寫 api 文件,不管是給前端、移動端等提供更好的對接,還是以後為了以後交接方便,都會要求寫 api 文件。 而手寫 api 文件的話有諸多痛點: 文件更新的時候,需要再次傳送給對接人 介面太對,手寫文件很難管理 介面返回的結果不明確 不能直接線上測試介面,通常需要使

Spring Boot 2.X(六)應用監控之 Spring Boot Actuator 使用及配置

Actuator 簡介 Actuator 是 Spring Boot 提供的對應用系統的自省和監控功能。通過 Actuator,可以使用資料化的指標去度量應用的執行情況,比如檢視伺服器的磁碟、記憶體、CPU等資訊,系統的執行緒、gc、執行狀態等等。 Actuator 通常通過使用 HTTP 和 JMX 來管理

Spring Boot 2.X(八)整合 Spring Security-登入認證和許可權控制

前言 在企業專案開發中,對系統的安全和許可權控制往往是必需的,常見的安全框架有 Spring Security、Apache Shiro 等。本文主要簡單介紹一下 Spring Security,再通過 Spring Boot 整合開一個簡單的示例。 Spring Security 什麼是 Spring Se

Spring Boot 2.X()自定義註冊 Servlet、Filter、Listener

前言 在 Spring Boot 中已經移除了 web.xml 檔案,如果需要註冊新增 Servlet、Filter、Listener 為 Spring Bean,在 Spring Boot 中有兩種方式: 使用 Servlet 3.0 API 的註解 @WebServlet、@WebFilter、@Lis

Spring Boot系列教程 Mybatis使用分頁外掛PageHelper

一.前言 上篇部落格中介紹了spring boot整合mybatis的方法,基於上篇文章這裡主要介紹如何使用分頁外掛PageHelper。在MyBatis中提供了攔截器介面,我們可以使用PageHelp最為一個外掛裝入到SqlSessionFactory,實現攔截器功能。

Spring Boot 2.x基礎教程快速入門

開發十年,就只剩下這套架構體系了! >>>   

Spring Boot 2.x基礎教程工程結構推薦

Spring Boot框架本身並沒有對工程結構有特別的要求,但是按照最佳實踐的工程結構可以幫助我們減少可能會遇見的坑,尤其是Spr

Spring Boot 2.x基礎教程構建RESTful API與單元測試

首先,回顧並詳細說明一下在快速入門中使用的@Controller、@RestController、@RequestMapping註

Spring Boot 2.x基礎教程使用Swagger2構建強大的API文件

隨著前後端分離架構和微服務架構的流行,我們使用Spring Boot來構建RESTful API專案的場景越來越多。通常我們的一個RESTful API就有可能要服務於多個不同的開發人員或開發團隊:IOS開發、Android開發、Web開發甚至其他的後端服務等。為了減少與其他團隊平時開發期間的頻繁溝通成本,傳

Spring Boot 2.x基礎教程JSR-303實現請求引數校驗

請求引數的校驗是很多新手開發非常容易犯錯,或存在較多改進點的常見場景。比較常見的問題主要表現在以下幾個方面: 僅依靠前端框架解決引數校驗,缺失服務端的校驗。這種情況常見於需要同時開發前後端的時候,雖然程式的正常使用不會有問題,但是開發者忽略了非正常操作。比如繞過前端程式,直接模擬客戶端請求,這時候就會突然在

Spring Boot 2.x基礎教程Swagger介面分類與各元素排序問題詳解

之前通過Spring Boot 2.x基礎教程:使用Swagger2構建強大的API文件一文,我們學習瞭如何使用Swagger為Spring Boot專案自動生成API文件,有不少使用者留言問了關於文件內容的組織以及排序問題。所以,就特別開一篇詳細說說Swagger中文件內容如何來組織以及其中各個元素如何控制

Spring Boot 2.x 基礎案例整合Dubbo 2.7.3+Nacos1.1.3(最新版)

1、概述 本文將介紹如何基於Spring Boot 2.x的版本,通過Nacos作為配置與註冊中心,實現Dubbo服務的註冊與消費。 整合元件的版本說明: Spring Boot 2.1.9 Dubbo 2.7.3 Nacos 1.1.3 本文的亮點: 1.採用yml方式進行dubbo的配置。 2.

Spring Boot 2.x 基礎案例整合Dubbo 2.7.3+Nacos1.1.3(配置中心)

本文原創首發於公眾號:Java技術乾貨 1、概述 本文將Nacos作為配置中心,實現配置外部化,動態更新。這樣做的優點:不需要重啟應用,便可以動態更新應用裡的配置資訊。在如今流行的微服務應用下,將應用的配置統一管理,顯得尤為重要。 上一篇寫了《Spring Boot 2.x 基礎案例:整合Dubbo

Spring Boot 2.x基礎教程Swagger靜態文件的生成

前言 通過之前的兩篇關於Swagger入門以及具體使用細節的介紹之後,我們已經能夠輕鬆地為Spring MVC的Web專案自動構建出API文件了。如果您還不熟悉這塊,可以先閱讀: Spring Boot 2.x基礎教程:使用Swagger2構建強大的API文件 Spring Boot 2.x基礎教程:Swa

Spring Boot 2.x基礎教程使用JdbcTemplate訪問MySQL資料庫

在第2章節中,我們介紹瞭如何通過Spring Boot來實現HTTP介面,以及圍繞HTTP介面相關的單元測試、文件生成等實用技能。但是,這些內容還不足以幫助我們構建一個動態應用的服務端程式。不論我們是要做App、小程式、還是傳統的Web站點,對於使用者的資訊、相關業務的內容,通常都需要對其進行儲存,而不是像第

Spring Boot 2.x基礎教程預設資料來源Hikari的配置詳解

通過上一節的學習,我們已經學會如何應用Spring中的JdbcTemplate來完成對MySQL的資料庫讀寫操作。接下來通過本篇文章,重點說說在訪問資料庫過程中的一個重要概念:資料來源(Data Source),以及Spring Boot中對資料來源的建立與配置。 基本概念 在開始說明Spring Boot中

Spring Boot 2.x基礎教程使用國產資料庫連線池Druid

上一節,我們介紹了Spring Boot在JDBC模組中自動化配置使用的預設資料來源HikariCP。接下來這一節,我們將介紹另外一個被廣泛應用的開源資料來源:Druid。 Druid是由阿里巴巴資料庫事業部出品的開源專案。它除了是一個高效能資料庫連線池之外,更是一個自帶監控的資料庫連線池。雖然HikariC