1. 程式人生 > >【Spring】SpringMVC之異常處理

【Spring】SpringMVC之異常處理

存儲 targe 存在 cnblogs del file 處理機制 href click

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之異常處理