在 Java Web 系統開發中,無論是 Controller 層、Service 層仍是 Dao 層,都有可能拋出異常。若是在每一個方法中加上各類 try catch 的異常處理代碼,那樣會使代碼很是繁瑣。在Spring MVC 中,咱們能夠將全部類型的異常處理從各個單獨的方法中解耦出來,進行異常信息的統一處理和維護。html
在 Spring MVC 中全局異常捕獲處理的解決方案一般有兩種方式:git
1.使用 @ControllerAdvice + @ExceptionHandler 註解進行全局的 Controller 層異常處理。github
2.實現 org.springframework.webb.servlet.HandlerExceptionResolver 接口中的 resolveException 方法。web
@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 能夠自定義,以下:spring
類型 | 描述 |
---|---|
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。數據庫
視圖控制器配置數組
@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>
@Controller public class TestController { @GetMapping("/index") public String hello() { int x = 1 / 0; return "hello"; } }
瀏覽器訪問:http://127.0.0.1:8080/index
安全
@ControllerAdvice 還能結合 @ModelAttribute 、@InitBinder 註解一塊兒使用,實現全局數據綁定和全局數據預處理等功能。
@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,而不是真實的異常對象。
@Controller public class TestController { @GetMapping("/test") public String test() { String[] ss = new String[] { "1", "2" }; System.out.print(ss[2]); return "hello"; } }
測試前先把 @ControllerAdvice 註釋了。
瀏覽器訪問:http://127.0.0.1:8080/test
app
非特殊說明,本文版權歸 朝霧輕寒 全部,轉載請註明出處.
原文標題:Spring Boot 2.X(十一):全局異常處理
原文地址: https://www.zwqh.top/article/info/20
若是文章對您有幫助,請掃碼關注下個人公衆號,文章持續更新中...