先導Spring的各種基本依賴,這里就不再說明
一、使用@ControllerAdvice和@ExceptionHandler注解的方式
1、自定義的異常類
package com.json.exception; public class BookException extends RuntimeException { public BookException() { } public BookException(String message) { super(message); } public BookException(String message, Throwable cause) { super(message, cause); } public BookException(Throwable cause) { super(cause); } public BookException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } }
2、通過@ControllerAdvice和@ExceptionHandler來配置異常處理
注意@ControllerAdvice注解一定要在<context:component-scan>中掃描到
package com.json.exception; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import java.util.HashMap; import java.util.Map; /*@ControllerAdvice會被<context:component-scan>掃描;該類使用@ExceptionHandler注解修飾的方法將 會應用到所有請求處理方法上*/ @ControllerAdvice public class GlobalExceptionHandler { //處理Exception類型異常 @ExceptionHandler(value = Exception.class) public ModelAndView globalErrorHandler(Exception e) throws Exception{ ModelAndView mv = new ModelAndView(); mv.addObject("ex",e); mv.setViewName("error"); return mv; } //處理OrderException類型異常 @ResponseBody @ExceptionHandler(value = BookException.class) public Object bookErrorHandler(Exception e) throws Exception{ //創建返回對象map並設置屬性,其會被@ResponseBody注解轉換為json返回 Map<String,Object> map = new HashMap<>(); map.put("code",100); map.put("message",e.getMessage()); map.put("data","請求失敗"); return map; } }
3、測試的controller
package com.json.controller; import com.json.exception.BookException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * 測試springmvc的自定義返回異常並返回頁面 */ @Controller public class ExceptionController { @RequestMapping("find") public String find(String name){ if (name == null){ throw new NullPointerException("用戶名不存在"); } return "success"; } @RequestMapping("delete") public String delete(){ try { int x = 5/0; return "success"; }catch (Exception e){ e.printStackTrace(); throw new BookException("刪除圖書失敗"); //自定義異常處理 } } }
4、定制jsp進行訪問測試
exceptionTest.jsp
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>springmvc異常處理測試</title> <script type="text/javascript" src="${pageContext.request.contextPath}/static/js/jquery.js"></script> <script type="text/javascript"> $(function () { $("#delete").click(function () { $.post("${pageContext.request.contextPath}/delete",null, function (data) { //處理異常 if (data.message){ alert("與服務器交互出現異常:"+data.message); } else { //獲取服務器響應,處理數據 } } ) }) }) </script> </head> <body> <a href="${pageContext.request.contextPath}/find">全局異常處理后放回錯誤頁面</a> <button id="delete">點擊此按鈕,得到自定義異常處理(返回json)</button> </body> </html>
error.jsp
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>異常頁面</title> </head> <body> <h1>異常頁面</h1> 異常信息:${requestScope.ex.message} </body> </html>
5、訪問exceptionTest.jsp
得到全局異常后的頁面:
得到自定義異常后的頁面:
二、使用SimpleMappingExceptionResolver實現集成異常處理
1、在SpringMVC的配置文件l中增加SimpleMappingExceptionResolver配置:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <!-- 定義默認的異常處理頁面,當該異常類型的注冊時使用 --> <property name="defaultErrorView" value="error"></property> <!-- 定義異常處理頁面用來獲取異常信息的變量名,默認名為exception --> <property name="exceptionAttribute" value="ex"></property> <!-- 定義需要特殊處理的異常,用全路徑類名作為key,異常處理頁面名作為值(跳轉至頁面時會把excepiton帶上) --> <property name="exceptionMappings"> <props> <prop key="cn.basttg.core.exception.BookException">book-error</prop> <prop key="cn.basttg.core.exception.UserException">user-error</prop> <!-- 這里還可以繼續擴展對不同異常類型的處理 --> </props> </property> </bean>
使用SimpleMappingExceptionResolver進行異常處理,具有集成簡單、有良好的擴展性、對已有代碼沒有入侵性等優點,但該方法僅能獲取到異常信息,若在出現異常時,對需要獲取除異常以外的數據的情況不適用。
三、未捕獲異常的處理
對於Unchecked Exception而言,由於代碼不強制捕獲,往往被忽略,如果運行期產生了Unchecked Exception,而代碼中又沒有進行相應的捕獲和處理,則我們可能不得不面對尷尬的404、500……等服務器內部錯誤提示頁面。
我們需要一個全面而有效的異常處理機制。目前大多數服務器也都支持在Web.xml中通過<error-page>(Websphere/Weblogic)或者<error-code>(Tomcat)節點配置特定異常情況的顯示頁面。修改web.xml文件,增加以下內容:
<!-- 出錯頁面定義 --> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/500.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/500.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/404.jsp</location> </error-page> <!-- 這里可繼續增加服務器錯誤號的處理及對應顯示的頁面 -->