1. 程式人生 > >SpringMVC攔截器與異常處理(六)

SpringMVC攔截器與異常處理(六)

在我們SpringMVC中也可以使用攔截器對使用者的請求進行攔截,使用者可以自定義攔截器來實現特定的功能。自定義攔截器必須要實現HandlerInterceptor介面

package com.spring.mvc.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/** * @author:SimpleWu * @to:攔截器執行流程:preHandle - 目標方法 - postHandle -渲染檢視 - afterCompletion */ public class MyInterceptor implements HandlerInterceptor{ /** * 渲染檢視之後被呼叫 * 釋放資源 */ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception { System.out.println("[MyInterceptor] afterCompletion"); } /** * 該方法是在目標方法之後,渲染檢視之前被呼叫 * 可以對請求域中的引數或檢視做出修改 */ @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception { System.out.println("[MyInterceptor] postHandle"); } /** * 該方法在目標方法前呼叫 * 1)如果返回值為true則繼續呼叫後續的攔截器和目標方法 * 2)如果返回值為false則不會呼叫後續的攔截器和目標方法 * 可以考慮做許可權,日誌。 */ @Override public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { System.out.println("[MyInterceptor] preHandle : 目標方法之前被呼叫。"); return true; } }

然後我們需要在SpringMVC中配置攔截器。

<mvc:interceptors>
        <!-- 配置自定義攔截器 -->
        <bean id="myInterceptor" class="com.spring.mvc.interceptor.MyInterceptor"/>
        <mvc:interceptor>
            <!-- 配置攔截器的作用路徑 -->
            <mvc:mapping path="/user/*"/>
            <!-- 
                配置攔截器不作用的路徑
                <mvc:exclude-mapping path=""/>
             -->
            <bean class="com.spring.mvc.interceptor.UserInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

如果我們配置了作用的路徑那麼我們現在只有user/*後面的請求它才會被我們的攔截器給攔截。

在我們攔截器中執行順序:首先呼叫preHandler方法然後進入請求的業務方法之後出來的時候會先呼叫postHandler這個方法(業務方法前,檢視渲染後),最後檢視渲染之後呼叫攔截器的afterCompletion方法。

如果我們有多個攔截器那麼他會按照配置順序執行preHandler,按逆方向執行postHandler與agterCompletion方法。

假如我們有兩個攔截器,在第一個攔截器的preHandler中返回false那麼所有的方法都不會執行,如果我們在第二個攔截器返回false第一個攔截器還會多執行一個afterCompletion方法。

SpringMVC異常處理

在SpringMVC中異常的處理與Struts2有點類似。

SpringMVC通過HandlerExceptionResolver處理程式異常,包括Handler對映,資料繫結以及目標方法執行時所發生的異常。

SpringMVC中預設是沒有加裝載HandlerExceptionResolver,我們需要在SpringMVC.xml中配置

<mvc:annotation-driven />

我們可以在Controller類中定義一個區域性(方法所在類)的異常處理的方法

/**
     *    在這個方法中可以加入Exception型別的引數,該引數即對於發生的異常物件
     *    入參中不能傳入map,若希望吧異常資訊傳到頁面上需要使用ModelAndView作為返回值 
     */
    @ExceptionHandler({NullPointerException.class})
    public String handlerNullPointerException(Exception ex){
        System.out.println("異常 : " + ex);
        return "error";
    }

這個方法他會針對這個類中的NullPointerException異常將他捕獲,然後執行這個方法。如果我們希望在頁面上顯示異常資訊的話我們只需要返回ModelAndView即可。

除了這種區域性異常我們還可以配置全域性異常處理類,這個類需要使用註解@ControllerAdvice修飾。

package com.spring.mvc.exceptionprocess;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

/**
 * @author SimpleWu
 * @ControllerAdvice:如果在當前Handler找不到當前方法出現的異常則將來這個註解標記的類中查詢處理異常。
 * 意為定義一個全域性異常
 */
@ControllerAdvice
public class UserException {
    
    @ExceptionHandler({NullPointerException.class})
    public ModelAndView handlerNullPointerException(Exception ex){
        System.out.println("[異常] : " + ex);
        ModelAndView mav = new ModelAndView("error");
        mav.addObject("exception",ex);
        return mav;
    }
}

當然在開發我們可能在上面的類中有兩個方法例如一個是RuntimeException和NullPointerException那麼他會呼叫那個捕獲方法呢?

它不會應為RuntimeException可以匹配就匹配這個他會根據最靠近這個異常的型別去匹配。

定製異常頁面

在網站中如果我們發生頁面不存在我們能夠看到頁面顯示:

在這裡我們可以自定義異常顯示。我們可以定義一個異常類使用@ResponseStatus註解修飾

package com.spring.mvc.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

/**
 * @author SimpleWu
 * 當捕獲當這個異常後更改錯誤提示
 */
@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="使用者密碼為空")
public class UserPassIsNullException extends RuntimeException{
    private static final long serialVersionUID = 1L;
}

在這裡我們定義了一個異常,如果在請求的方法中丟擲我們的異常,頁面就會顯示我們定製的狀態碼與提示資訊。

SimpleMappingExceptionResolver:

如果希望對異常進行統一處理我們可以裝配這個bean,將它的異常類名對映為檢視名,發生異常時使用對應檢視報告異常

<!-- 
        配置SimpleMappingExceptionResolverl來對映異常
        相當於捕獲一個全域性異常
     -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        
        <!-- 自定義異常屬性名字 -->
        <property name="exceptionAttribute" value="ex"/>
        <property name="exceptionMappings">
            <props>
                <!-- 捕獲到java.lang.ArithmeticException異常跳轉error.jsp頁面 -->
                <prop key="java.lang.ArithmeticException">error</prop>
            </props>
        </property>
    </bean>

如果我們捕獲到這個算數異常那麼我們就會返回error檢視。本該在jsp中我們的頁面上顯示異常預設使用exception現在名字換成了ex