【Spring】SpringMVC之異常處理
java中的異常分為兩類,一種是運行時異常,一種是非運行時異常。在JavaSE中,運行時異常都是通過try{}catch{}捕獲的,這種只能捕獲顯示的異常,通常項目上拋出的異常都是不可預見。那麽我們能夠有什麽方法能夠解決這種問題嗎?當然有,SpringMVC中的異常處理機制就很好的做到了這一點。
SpringMVC中的異常處理一共有3種方式
- (1)使用Spring MVC提供的簡單異常處理器SimpleMappingExceptionResolver;
- (2)實現Spring的異常處理接口HandlerExceptionResolver 自定義自己的異常處理器;
- (3)[email protected]
(1)使用Spring MVC提供的SimpleMappingExceptionResolver
直接將SimpleMappingExceptionResolver
類配置到SpringMVC配置文件中
<!-- 只是對全局的Controller有效果 所有的被RequestMapping註解所添加的方法中的異常才有效果 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- key: 異常的類全稱 value: ModelAndView中的viewName 表示當key指定的異常產生時 , 則請求轉發至 value指向的視圖 --> <prop key="java.lang.Exception">errorPage</prop> </props> </property> </bean>
從配置文件上可以看出,如果發生了異常就跳轉到名為errorPage的視圖上。
完整的applicationContext.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd"> <!-- 開啟註解掃描 --> <context:component-scan base-package="cn"></context:component-scan> <!-- 開啟mvc註解掃描 --> <mvc:annotation-driven/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"></property> <property name="suffix" value=".jsp"></property> </bean> <!-- 只是對全局的Controller有效果 所有的被RequestMapping註解所添加的方法中的異常才有效果 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- key: 異常的類全稱 value: ModelAndView中的viewName 表示當key指定的異常產生時 , 則請求轉發至 value指向的視圖 --> <prop key="java.lang.Exception">errorPage</prop> </props> </property> </bean> </beans>applicationContext.xml
使用這種方式的異常處理就是簡單,但是問題顯而易見,就是發生了異常自動就跳轉到錯誤頁面,那麽這不利於後臺對錯誤日誌的收集。
(2)實現Spring的異常處理接口HandlerExceptionResolver 自定義自己的異常處理器
使用方式如下:
@Component public class MyException implements HandlerExceptionResolver { @Override public ModelAndView resolveException(參數...) { //操作... } }
在自定義異常處理器中,我們就可以很方便對異常信息進行各種操作操作,下面是一個能收集錯誤信息的自定義異常處理器:
SpringMVC的配置文件中需要負責打開掃描:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd"> <!-- 開啟註解掃描 --> <context:component-scan base-package="cn"></context:component-scan> <!-- 開啟mvc註解掃描 --> <mvc:annotation-driven/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"></property> <property name="suffix" value=".jsp"></property> </bean> </beans>applicationContext.xml
自定義的異常類:
package cn.shop.exception; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import cn.shop.util.ExceptionUtil; /** * 用來在全局 處理Controller異常 */ @Component public class SpringMVCException implements HandlerExceptionResolver { /** * 如果這個類的對象, 存在於容器中, 則當前的項目中, 所有的Controller 出現的異常, 都會到這個方法中 * * 參數1. 請求對象 * 參數2. 響應對象 * 參數3. 出現異常時的 Method對象 * 參數4. 出現異常時的異常信息 * * 返回值, 會被ViewResolver解析 */ @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object method,Exception e) { System.out.println("出現異常的方法:"+method.toString()); //request.getQueryString(): 獲取get請求時的參數列表 String paras = request.getQueryString(); System.out.println("出現了異常, 出現異常時的請求參數:"+paras); System.out.println("--------------------------------------"); System.out.println("---------- 異常信息如下 ---------"); System.out.println("--------------------------------------"); e.printStackTrace(); //存儲到異常日誌 ExceptionUtil.toException(e); //跳轉 return new ModelAndView( "error"); } }SpringMVCException.java
存儲異常的工具類:
package cn.shop.util; import java.io.File; import java.io.FileOutputStream; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; /** * 用來收集異常日誌 * * JavaEE web階段 * * 當產生異常時, 應把異常收集起來 , * * 存儲到 * 本地文件 * 網絡存儲 * 短信發送 * 郵件 */ public class ExceptionUtil { /** * * 存儲: * 在存儲的目錄下 ,按照每天的日期創建單獨文件夾 * * 每天的文件夾中, 異常日誌存儲的文件, 一個異常一個文件, 文件名稱按照時-分-秒-毫秒的格式存儲 * * * @param e 要存儲的異常信息 * @param exceptionPath 要存儲的位置: 是一個文件夾, 文件夾可以不存在 * @throws Exception */ public static void toException(Exception e,File exceptionPath) throws Exception{ if(!exceptionPath.exists()){ //創建文件夾 exceptionPath.mkdirs(); } Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String day = sdf.format(date); //創建每天的異常文件夾 File dayDir = new File(exceptionPath, day); if(!dayDir.exists()) dayDir.mkdirs(); //創建本次異常存儲的文件 SimpleDateFormat sdf2 = new SimpleDateFormat("HH-mm-ss-sss"); String fileName = sdf2.format(date); File file = new File(dayDir, fileName+".txt"); //創建一個字符打印流 , 指向創建的這個文件 PrintWriter pw = new PrintWriter(new FileOutputStream(file)); //將異常信息輸出至這個文件 e.printStackTrace(pw); pw.close(); } /** * * @param e 要存儲的異常信息 , 存儲的位置 ,在F://log文件夾中 */ public static void toException(Exception e){ try { toException(e,new File("F://log")); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } }ExceptionUtil.java
(3)@ExceptionHandler註解實現異常處理
package cn.xdl.controller; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class UserController { @RequestMapping("/login.do") public String UserrLogin(String name,String password){ //從數據庫進行數據對比... //將結果值返回 return "loginResult"; } /** * 當前這個Controller類 ,被RequestMapping所註解的方法 如果出現了異常 ,[email protected]的方法 , 如果存在, 則執行 * * 這個方法的寫法, 與使用直接方式的Controller基本一致 * 它的參數列表中, 可以根據需求選擇如下參數: * HttpSession / HttpServletRequest /HttpServletResponse / Exception */ @ExceptionHandler public String hahaha(Exception e,HttpServletRequest request){ System.out.println("請求時的參數:"+request.getQueryString()); System.out.println("---------------------------------"); System.out.println("----------- 請看異常信息 -----------"); System.out.println("---------------------------------"); e.printStackTrace(); return "error"; } }
上面這三種方式,各不影響,如果使用了多種方式的話,那麽以離異常近的處理機制為準(就近原則)。
參考文章:
Java中自定義異常
【Spring】SpringMVC之異常處理