前言
在 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
@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
示例代碼
非特殊說明,本文版權歸 朝霧輕寒 所有驮吱,轉載請注明出處.
原文標題:Spring Boot 2.X(十一):全局異常處理
原文地址: https://www.zwqh.top/article/info/20
如果文章對您有幫助茧妒,請掃碼關注下我的公眾號,文章持續(xù)更新中...