SpringMVC Interceptor

SpringMVC Interceptor

API: http://docs.spring.io/spring-framework/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/servlet/HandlerInterceptor.html

DOCS: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-handlermapping-interceptor

Blog: http://haohaoxuexi.iteye.com/blog/1750680

Interceptor 概要

接口原型

Spring 的 Interceptor (攔截器)是通過 HandlerInterceptor 接口實現的。

package org.springframework.web.servlet;

public interface HandlerInterceptor {
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception;
    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;
    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;
}

Spring 的 handle mapping(處理器映射)機制包含handler interceptors(處理攔截器),當你需要需要對某一請求應用特定的功能時,攔截器會變得很有用,例如身份檢查。

位於處理映射中的攔截器必須實現 org.springframework.web.servlet 包下的 HandlerInterceptor 接口。這個定義了三個方法:

  • preHandle(..) 會在實際的 handler 執行之前被調用。
  • postHandle(..) 會在 handler 執行之後被調用。
  • afterCompletion(..) 會在整個請求完成 之後被調用。
    這三個方法爲各種 preprocessing 和 postprocessing (前處理和後處理)提供了足夠的靈活性。

  • 說明:preHandle(..)方法返回一個布爾值,你可以使用這個方法來中斷繼續執行 execution chain(執行鏈)。當此方法返回 true, handler 執行鏈會繼續執行;當返回 false,DispatcherServlet 認爲攔截器自身已經完成了對請求的處理(例如,呈現一個適當的視圖),就不會繼續執行其他攔截器,也不會執行執行鏈中的實際的 handler。

preHandle API

攔截 handler 的執行。在 HeandlerMapping 決定了一個合適的 handler 對象之後,但在 HandlerAdapter 調用 handler 之前被調用。

DispatcherServlet 處理 execution chain(執行鏈)中的 handler,執行鏈由數個攔截器組成,handler 在執行鏈的最後。通過此方法,每一個攔截器都可以決定放棄後面的執行鏈,典型地做法如:發送一個HTTP錯誤,或寫入一個自定義響應。

返回值:
true:如果執行鏈要處理下一個攔截器或handler。否則,DispatcherServlet 假定此攔截器自己已處理了響應。

postHandle API

攔截 handler 的執行。在 HandlerAdapter 實際調用 handler 之後,但在 DispatcherServlet 渲染 view 之前被調用。可以暴露額外的 modle 對象到參數中的 ModelAndView。

DispatcherServlet 處理 execution chain(執行鏈)中的 handler,執行鏈由數個攔截器組成,handler 在執行鏈的最後。通過此方法,每一個攔截器都可以執行一個後處理,按執行鏈順序的逆序執行。

afterCompletion API

完成請求處理之後的回調,在渲染 view 之後。將在任何 handler 執行結果上調用,因此允許做適當的資源清理。

注意:只在攔截器的 preHandle 方法成功執行完成且返回 true 時才被調用!

與 postHandle 方法一樣。此方法按攔截器在執行鏈中的順序逆序調用。因此第一個攔截器(的此方法)將在最後被調用。

Interceptor 實現

方式一:實現 HandlerInterceptor 接口

public class FirstInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("FirstInterceptor ... preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("FirstInterceptor ... postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("FirstInterceptor ... afterCompletion");
    }
}

方式二:實現 WebRequestInterceptor 接口

WebRequestInterceptor 是另外一個接口。原型是:

package org.springframework.web.context.request;

public interface WebRequestInterceptor {
    void preHandle(WebRequest request) throws Exception;
    void postHandle(WebRequest request, ModelMap model) throws Exception;
    void afterCompletion(WebRequest request, Exception ex) throws Exception;
}

preHandle 方法

在請求的 handler 調用之前攔截執行。
允許在此時準備上下文資源(比如 Hibernate Session),把它們暴露到 request attributes 中,或者暴露爲 thread-local 對象。

postHandle 方法

在請求的 handler 成功執行之後,在 view 渲染之前,攔截執行。
允許在 handler 執行成功之後,修改上下文資源(例如:清除 Hibernate Session)。

afterCompletion 方法

view 渲染之後的回調。將在 handler 執行的結果上調用,因此允許此時做是的適當的資源釋放。
注意:僅在此攔截器的 preHandle 方法成功執行完成的情況下被調用!

說明

  • preHandle方法:方法的返回值爲 void,不同於 HandlerInterceptor,一般被用於資源準備工作。可以調用 WebRequest 的 setAttribute(name, value, scope) 方法把相關資源放入 WebRequest 的屬性中。其中的 scope 作用域值可以爲:

    • WebRequest.SCOPE_REQUEST:值爲0,代表僅在在 request 中訪問。
    • WebRequest.SCOPE_SESSION:值爲1,如果環境允許的話它代表的是一個局部的隔離的session,否則就代表普通的session,並且在該session範圍內可以訪問。
    • WebRequest.SCOPE_GLOBAL_SESSION:值爲2,如果環境允許的話,它代表的是一個全局共享的session,否則就代表普通的session,並且在該session 範圍內可以訪問。
  • postHandle方法:可以在這個方法裏面通過改變數據模型 ModelMap 來改變數據的展示。參數:

    • WebRequest: 是用於傳遞整個請求數據的,比如在 preHandle 中準備的數據都可以通過 WebRequest 來傳遞和訪問。
    • ModelMap: 就是 Controller 處理之後返回的 Model 對象,我們可以通過改變它的屬性來改變返回的 Model 模型。
  • afterCompletion方法:該方法會在整個請求處理完成,也就是在視圖返回並被渲染之後執行。可以在方法中可以進行資源的釋放操作。參數:

    • WebRequest:可以把我們在preHandle 中準備的資源傳遞到這裏進行釋放。
    • Exception:表示的是當前請求的異常對象,如果在 Controller 中拋出的異常已經被 Spring 的異常處理器給處理了的話,那麼這個異常對象就是是 null。

在 SpringMVC 中使用 Interceptor

這裏只介紹 XML 聲明方式。

使用 <mvc:interceptors> 標籤

方式一
直接定義一個 Interceptor 實現類的bean對象。使用這種方式聲明的 Interceptor 攔截器將會對所有的請求進行攔截。

<mvc:interceptors>
    <bean class="com.my.FirstInterceptor"/>
</mvc:interceptors>

方式二
使用 <mvc:interceptor> 標籤進行聲明。使用這種方式進行聲明的 Interceptor 可以通過 <mvc:mapping> 子標籤來定義需要進行攔截的請求路徑。

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/test/hello.do"/>
        <bean class="com.my.FirstInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章