springMVC提供的異常處理主要有兩種方式,一種是直接實現本身的HandlerExceptionResolver,固然這也包括使用Spring已經爲咱們提供好的SimpleMappingExceptionResolver和DefaultHandlerExceptionResolver,另外一種是使用註解的方式實現一個專門用於處理異常的Controller——ExceptionHandler。和以前同樣,前者至關於全局管理的異常,後者只針對當前controller有效javascript
首先定義一個全局異常類,能夠看出這個類會把異常打印在控制檯,而且放入model中,以即可以在jsp頁面上展現出來css
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; public class MyExceptionResolver implements HandlerExceptionResolver{ public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println("==============異常開始============="); ex.printStackTrace(); System.out.println("==============異常結束============="); //設置返回頁面爲error.jsp ModelAndView mv = new ModelAndView("error"); mv.addObject("exception", ex.toString().replaceAll("\n", "<br/>")); return mv; } }
而後在error.jsp中顯示異常html
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>應用程序異常 (500)</title> </head> <body> <div> <h1>應用程序異常</h1> <p>抱歉!您訪問的頁面出現異常,請稍後重試或聯繫管理員。</p> <p><a href="#">詳 情</a> <a href="javascript:history.back(-1)">返 回</a> </p> <div style="display:none;text-align: left;" id="err">${exception }</div> </div> </body> </html>
接着在springMVC.xml中配置這個異常java
<!--配置全局異常類--> <bean id="exceptionResolver" class="main.java.controller.MyExceptionResolver"/>
在控制器裏面模擬調用web
@RequestMapping(value = "/hello",method = RequestMethod.GET) public String hello(Model model){ String str = "asbd123"; //這裏會報NumberFormatException異常,而後spring會自動捕捉這個異常 int a = Integer.parseInt(str); return "hello"; }
而後訪問localhost:8888/hello,頁面就會顯示以下
面試
一樣的再控制檯會輸出咱們的異常信息
spring
到此這就是一個全局異常.app
局部異常使用使用@ExceptionHandler進行處理,具體以下jsp
使用@ExceptionHandler進行處理有一個很差的地方是進行異常處理的方法必須與出錯的方法在同一個Controller裏面測試
//建立處理異常的類,這個類會處理當前控制器下的Myexception這個異常 @ExceptionHandler(Myexception.class) public String getError(Myexception myexception,Model model){ System.out.println("==============異常開始============="); myexception.printStackTrace(); System.out.println("==============異常結束============="); model.addAttribute("exception",myexception.getMessage()); return "error"; } //當前這個請求會拋出異常 @RequestMapping(value = "/hello",method = RequestMethod.GET) public String hello(Model model) throws Myexception { if (true){ throw new Myexception("出錯了"); } return "hello"; }
對應的JSP視圖中會顯示出相應的錯誤信息
對應的控制檯也會輸出相應的信息
既然在SpringMVC中有兩種處理異常的方式,那麼就存在一個優先級的問題:
當發生異常的時候,SpringMVC會以下處理:
Spring實現了一個SimpleMappingExceptionResolver,這二者都是繼承自抽象類AbstractHandlerExceptionResolver,而AbstractHandlerExceptionResolver是實現了HandlerExceptionResolver接口的resolveException方法的,並由此抽取出兩個抽象方法,一個是在進行異常處理以前執行的方法prepareResponse(exception, response),一個是進行異常解析的doResolveException(request, response, handler, exception)方法。
SimpleMappingExceptionResolver,顧名思義就是經過簡單的映射關係來決定由哪一個視圖來處理當前的錯誤信息。SimpleMappingExceptionResolver提供了經過異常類型exceptionMappings來進行異常與視圖之間的映射關係,提供了在發生異常時經過statusCodes來映射異常返回的視圖名稱和對應的HttpServletResponse的返回碼。並且能夠經過defaultErrorView和defaultErrorCode來指定默認值,defaultErrorView表示當沒有在exceptionMappings裏面找到對應的異常類型時就返回defaultErrorView定義的視圖,defaultErrorCode表示在發生異常時當沒有在視圖與返回碼的映射關係statusCodes裏面找到對應的映射時默認返回的返回碼。在使用SimpleMappingExceptionResolver時,當發生異常的時候,SimpleMappingExceptionResolver將會把當前的異常對象放到自身屬性exceptionAttribute中,當沒有指定exceptionAttribute時,exceptionAttribute就是用默認值exception。
下面試一個其xml代碼的簡單配置
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="NumberFormatException">number</prop><!-- 表示當拋出NumberFormatException的時候就返回名叫number的視圖 --> <prop key="NullPointerException">null</prop> </props> </property> <property name="defaultErrorView" value="exception"/><!-- 表示當拋出異常但沒有在exceptionMappings裏面找到對應的異常時 返回名叫exception的視圖--> <property name="statusCodes"><!-- 定義在發生異常時視圖跟返回碼的對應關係 --> <props> <prop key="number">500</prop><!-- 表示在發生NumberFormatException時返回視圖number,而後這裏定義發生異常時視圖number對應的HttpServletResponse的返回碼是500 --> <prop key="null">503</prop> </props> </property> <property name="defaultStatusCode" value="404"/><!-- 表示在發生異常時默認的HttpServletResponse的返回碼是多少,默認是200 --> </bean>
下面是引起這些異常的測試代碼
@Controller @RequestMapping("/test") public class TestController { @RequestMapping("/null") public void testNullPointerException() { Blog blog = null; //這裏就會發生空指針異常,而後就會返回定義在SpringMVC配置文件中的null視圖 System.out.println(blog.getId()); } @RequestMapping("/number") public void testNumberFormatException() { //這裏就會發生NumberFormatException,而後就會返回定義在SpringMVC配置文件中的number視圖 Integer.parseInt("abc"); } @RequestMapping("/default") public void testDefaultException() { if (1==1) //因爲該異常類型在SpringMVC的配置文件中沒有指定,因此就會返回默認的exception視圖 throw new RuntimeException("Error!"); } }
最後在jsp頁面中能夠訪問這些異常
<%@ page language="java" import="java.util.*" pageEncoding="GB18030" isErrorPage="true"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'number.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> NumberFormatException. <br> <%=exception.getMessage() %><br/> <%=exception %><br/><span style="color: #3366ff;"><!-- 這是JSP中的內置對象exception --></span> <%=request.getAttribute("ex") %><br><span style="color: #3366ff;"><!-- 這是SpringMVC放在返回的Model中的異常對象 --></span> <%=request.getAttribute("javax.servlet.error.status_code") %><span style="color: #3366ff;"><!-- HttpServletResponse返回的錯誤碼信息,由於前面已經配置了NumberFormatException的錯誤碼返回值爲888,因此這裏應該顯示888 --></span> </body> </html>
參考資料:http://www.makeru.com.cn/