Spring MVC異常處理
在 Spring MVC 應用的開發中,不管是操作底層資料庫,還是業務層或控制層,都會不可避免地遇到各種可預知的、不可預知的異常。我們需要捕捉處理異常,才能保證程式不被終止。
Spring MVC 有以下 3 種處理異常的方式:
- 使用 Spring MVC 提供的簡單異常處理器 SimpleMappingExceptionResolver。
- 實現 Spring 的異常處理介面 HandlerExceptionResolver,自定義自己的異常處理器。
- 使用 @ExceptionHandler 註解實現異常處理
1. @ExceptionHandler
區域性異常處理僅能處理指定 Controller 中的異常。
示例 1:
@RequestMapping("/testExceptionHandle") public String testExceptionHandle(@RequestParam("i") Integer i) { System.out.println(10 / i); return "success"; }
顯然,當 i=0 時會產生算術運算異常。
下面在同一個類中定義處理異常的方法。
@ExceptionHandler({ ArithmeticException.class }) public String testArithmeticException(Exception e) { System.out.println("列印錯誤資訊 ===> ArithmeticException:" + e); // 跳轉到指定頁面 return "error"; }
注意:該註解不是加在產生異常的方法上,而是加在處理異常的方法上。
異常頁面 error.jsp 程式碼如下。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>錯誤頁面</title> </head> <body> 發生算術運算異常,請重新輸出資料! </body> </html>
訪問地址:http://localhost:8080/springmvcDemo2/testExceptionHandle?i=0,頁面跳轉到 error.jsp 頁面,執行結果如圖 1 所示。
圖 1:error.jsp頁面
控制器輸出結果如下。
列印錯誤資訊 ===> ArithmeticException:java.lang.ArithmeticException: / by zero
@ExceptionHandler 註解定義的方法優先順序問題:例如發生的是 NullPointerException,但是宣告的異常有 RuntimeException 和 Exception,這時候會根據異常的最近繼承關係找到繼承深度最淺的那個@ExceptionHandler 註解方法,即標記了 RuntimeException 的方法。
被 @ExceptionHandler 標記為異常處理方法,不能在方法中設定別的形參。但是可以使用 ModelAndView 向前臺傳遞資料。
使用區域性異常處理,僅能處理某個 Controller 中的異常,若需要對所有異常進行統一處理,可使用以下兩種方法。
2. HandlerExceptionResolver
Spring MVC 通過HandlerExceptionResolver 處理程式異常,包括處理器異常、資料繫結異常以及控制器執行時發生的異常。HandlerExceptionResolver 僅有一個介面方法,原始碼如下。
public interface HandlerExceptionResolver { @Nullable ModelAndView resolveException( HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex); }
發生異常時,Spring MVC 會呼叫resolveException() 方法,並轉到 ModelAndView 對應的檢視中,返回一個異常報告頁面反饋給使用者。
示例 2:在 net.biancheng.exception 包中建立一個 HandlerExceptionResolver 介面的實現類 MyExceptionHandler,程式碼如下。
package net.biancheng.exception; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; public class MyExceptionHandler implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) { Map<String, Object> model = new HashMap<String, Object>(); // 根據不同錯誤轉向不同頁面(統一處理),即異常與View的對應關係 if (arg3 instanceof ArithmeticException) { return new ModelAndView("error", model); } return new ModelAndView("error-2", model); } }
在 springmvc-servlet.xml 檔案中新增以下程式碼。
<!--託管MyExceptionHandler--> <bean class="net.biancheng.exception.MyExceptionHandler"/>
再次訪問 http://localhost:8080/springmvcDemo2/testExceptionHandle?i=0,頁面跳轉到 error.jsp 頁面,執行結果如上圖 1 所示。
3. SimpleMappingExceptionResolver
全域性異常處理可使用SimpleMappingExceptionResolver 來實現。它將異常類名對映為檢視名,即發生異常時使用對應的檢視報告異常。
示例 3:在 springmvc-servlet.xml 中配置全域性異常,程式碼如下。
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <!-- 定義預設的異常處理頁面,當該異常型別註冊時使用 --> <property name="defaultErrorView" value="error"></property> <!-- 定義異常處理頁面用來獲取異常資訊的變數名,預設名為exception --> <property name="exceptionAttribute" value="ex"></property> <!-- 定義需要特殊處理的異常,用類名或完全路徑名作為key,異常頁名作為值 --> <property name="exceptionMappings"> <props> <prop key="ArithmeticException">error</prop> <!-- 在這裡還可以繼續擴充套件對不同異常型別的處理 --> </props> </property> </bean>
再次訪問 http://localhost:8080/springmvcDemo2/testExceptionHandle?i=0,頁面跳轉到 error.jsp 頁面,執行結果如上圖 1 所示。
from
http://c.biancheng.net/spring_mvc/exception.html