天天看點

SpringMVC中使用Interceptor攔截器   一、定義Interceptor實作類   二、把定義的攔截器類加到SpringMVC的攔截體系中

springmvc中的interceptor攔截器也是相當重要和相當有用的,它的主要作用是攔截使用者的請求并進行相應的處理。比如通過它來進行權限驗證,或者是來判斷使用者是否登陸,或者是像12306那樣子判斷目前時間是否是購票時間。

   springmvc中的interceptor攔截請求是通過handlerinterceptor來實作的。在springmvc中定義一個interceptor非常簡單,主要有兩種方式,第一種方式是要定義的interceptor類要實作了spring的handlerinterceptor 接口,或者是這個類繼承實作了handlerinterceptor接口的類,比如spring已經提供的實作了handlerinterceptor接口的抽象類handlerinterceptoradapter ;第二種方式是實作spring的webrequestinterceptor接口,或者是繼承實作了webrequestinterceptor的類。

   handlerinterceptor接口中定義了三個方法,我們就是通過這三個方法來對使用者的請求進行攔截處理的。

   (1)prehandle(httpservletrequest request, httpservletresponse response, object handle)方法,顧名思義,該方法将在請求處理之前進行調用。springmvc中的interceptor是鍊式的調用的,在一個應用中或者說是在一個請求中可以同時存在多個interceptor。每個interceptor的調用會依據它的聲明順序依次執行,而且最先執行的都是interceptor中的prehandle方法,是以可以在這個方法中進行一些前置初始化操作或者是對目前請求的一個預處理,也可以在這個方法中進行一些判斷來決定請求是否要繼續進行下去。該方法的傳回值是布爾值boolean類型的,當它傳回為false時,表示請求結束,後續的interceptor和controller都不會再執行;當傳回值為true時就會繼續調用下一個interceptor的prehandle方法,如果已經是最後一個interceptor的時候就會是調用目前請求的controller方法。

   (2)posthandle(httpservletrequest request, httpservletresponse response, object handle, modelandview modelandview)方法,由prehandle方法的解釋我們知道這個方法包括後面要說到的aftercompletion方法都隻能是在目前所屬的interceptor的prehandle方法的傳回值為true時才能被調用。posthandle方法,顧名思義就是在目前請求進行處理之後,也就是controller方法調用之後執行,但是它會在dispatcherservlet進行視圖傳回渲染之前被調用,是以我們可以在這個方法中對controller處理之後的modelandview對象進行操作。posthandle方法被調用的方向跟prehandle是相反的,也就是說先聲明的interceptor的posthandle方法反而會後執行,這和struts2裡面的interceptor的執行過程有點類型。struts2裡面的interceptor的執行過程也是鍊式的,隻是在struts2裡面需要手動調用actioninvocation的invoke方法來觸發對下一個interceptor或者是action的調用,然後每一個interceptor中在invoke方法調用之前的内容都是按照聲明順序執行的,而invoke方法之後的内容就是反向的。

   (3)aftercompletion(httpservletrequest request, httpservletresponse response, object handle, exception ex)方法,該方法也是需要目前對應的interceptor的prehandle方法的傳回值為true時才會執行。顧名思義,該方法将在整個請求結束之後,也就是在dispatcherservlet渲染了對應的視圖之後執行。這個方法的主要作用是用于進行資源清理工作的。

下面是一個簡單的代碼說明:

SpringMVC中使用Interceptor攔截器   一、定義Interceptor實作類   二、把定義的攔截器類加到SpringMVC的攔截體系中

import javax.servlet.http.httpservletrequest;  

import javax.servlet.http.httpservletresponse;  

import org.springframework.web.servlet.handlerinterceptor;  

import org.springframework.web.servlet.modelandview;  

public class springmvcinterceptor implements handlerinterceptor {  

    /** 

     * prehandle方法是進行處理器攔截用的,顧名思義,該方法将在controller處理之前進行調用,springmvc中的interceptor攔截器是鍊式的,可以同時存在 

     * 多個interceptor,然後springmvc會根據聲明的前後順序一個接一個的執行,而且所有的interceptor中的prehandle方法都會在 

     * controller方法調用之前調用。springmvc的這種interceptor鍊式結構也是可以進行中斷的,這種中斷方式是令prehandle的返 

     * 回值為false,當prehandle的傳回值為false的時候整個請求就結束了。 

     */  

    @override  

    public boolean prehandle(httpservletrequest request,  

            httpservletresponse response, object handler) throws exception {  

        // todo auto-generated method stub  

        return false;  

    }  

     * 這個方法隻會在目前這個interceptor的prehandle方法傳回值為true的時候才會執行。posthandle是進行處理器攔截用的,它的執行時間是在處理器進行處理之 

     * 後,也就是在controller的方法調用之後執行,但是它會在dispatcherservlet進行視圖的渲染之前執行,也就是說在這個方法中你可以對modelandview進行操 

     * 作。這個方法的鍊式結構跟正常通路的方向是相反的,也就是說先聲明的interceptor攔截器該方法反而會後調用,這跟struts2裡面的攔截器的執行過程有點像, 

     * 隻是struts2裡面的intercept方法中要手動的調用actioninvocation的invoke方法,struts2中調用actioninvocation的invoke方法就是調用下一個interceptor 

     * 或者是調用action,然後要在interceptor之前調用的内容都寫在調用invoke之前,要在interceptor之後調用的内容都寫在調用invoke方法之後。 

    public void posthandle(httpservletrequest request,  

            httpservletresponse response, object handler,  

            modelandview modelandview) throws exception {  

     * 該方法也是需要目前對應的interceptor的prehandle方法的傳回值為true時才會執行。該方法将在整個請求完成之後,也就是dispatcherservlet渲染了視圖執行, 

     * 這個方法的主要作用是用于清理資源的,當然這個方法也隻能在目前這個interceptor的prehandle方法的傳回值為true時才會執行。 

    public void aftercompletion(httpservletrequest request,  

            httpservletresponse response, object handler, exception ex)  

    throws exception {  

}  

  webrequestinterceptor中也定義了三個方法,我們也是通過這三個方法來實作攔截的。這三個方法都傳遞了同一個參數webrequest,那麼這個webrequest是什麼呢?這個webrequest是spring定義的一個接口,它裡面的方法定義都基本跟httpservletrequest一樣,在webrequestinterceptor中對webrequest進行的所有操作都将同步到httpservletrequest中,然後在目前請求中一直傳遞。

   (1)prehandle(webrequestrequest)方法。該方法将在請求處理之前進行調用,也就是說會在controller方法調用之前被調用。這個方法跟handlerinterceptor中的prehandle是不同的,主要差別在于該方法的傳回值是void,也就是沒有傳回值,是以我們一般主要用它來進行資源的準備工作,比如我們在使用hibernate的時候可以在這個方法中準備一個hibernate的session對象,然後利用webrequest的setattribute(name, value,

scope)把它放到webrequest的屬性中。這裡可以說說這個setattribute方法的第三個參數scope,該參數是一個integer類型的。在webrequest的父層接口requestattributes中對它定義了三個常量:

   scope_request:它的值是0,代表隻有在request中可以通路。

   scope_session:它的值是1,如果環境允許的話它代表的是一個局部的隔離的session,否則就代表普通的session,并且在該session範圍内可以通路。

   scope_global_session:它的值是2,如果環境允許的話,它代表的是一個全局共享的session,否則就代表普通的session,并且在該session範圍内可以通路。

   (2)posthandle(webrequestrequest, modelmap model)方法。該方法将在請求處理之後,也就是在controller方法調用之後被調用,但是會在視圖傳回被渲染之前被調用,是以可以在這個方法裡面通過改變資料模型modelmap來改變資料的展示。該方法有兩個參數,webrequest對象是用于傳遞整個請求資料的,比如在prehandle中準備的資料都可以通過webrequest來傳遞和通路;modelmap就是controller處理之後傳回的model對象,我們可以通過改變它的屬性來改變傳回的model模型。

   (3)aftercompletion(webrequestrequest, exception ex)方法。該方法會在整個請求處理完成,也就是在視圖傳回并被渲染之後執行。是以在該方法中可以進行資源的釋放操作。而webrequest參數就可以把我們在prehandle中準備的資源傳遞到這裡進行釋放。exception參數表示的是目前請求的異常對象,如果在controller中抛出的異常已經被spring的異常處理器給處理了的話,那麼這個異常對象就是是null。

   下面是一個簡單的代碼說明:

SpringMVC中使用Interceptor攔截器   一、定義Interceptor實作類   二、把定義的攔截器類加到SpringMVC的攔截體系中

import org.springframework.ui.modelmap;  

import org.springframework.web.context.request.webrequest;  

import org.springframework.web.context.request.webrequestinterceptor;  

public class allinterceptor implements webrequestinterceptor {  

     * 在請求處理之前執行,該方法主要是用于準備資源資料的,然後可以把它們當做請求屬性放到webrequest中 

    public void prehandle(webrequest request) throws exception {  

        system.out.println("allinterceptor...............................");  

        request.setattribute("request", "request", webrequest.scope_request);//這個是放到request範圍内的,是以隻能在目前請求中的request中擷取到  

        request.setattribute("session", "session", webrequest.scope_session);//這個是放到session範圍内的,如果環境允許的話它隻能在局部的隔離的會話中通路,否則就是在普通的目前會話中可以通路  

        request.setattribute("globalsession", "globalsession", webrequest.scope_global_session);//如果環境允許的話,它能在全局共享的會話中通路,否則就是在普通的目前會話中通路  

     * 該方法将在controller執行之後,傳回視圖之前執行,modelmap表示請求controller處理之後傳回的model對象,是以可以在 

     * 這個方法中修改modelmap的屬性,進而達到改變傳回的模型的效果。 

    public void posthandle(webrequest request, modelmap map) throws exception {  

        for (string key:map.keyset())  

            system.out.println(key + "-------------------------");;  

        map.put("name3", "value3");  

        map.put("name1", "name1");  

     * 該方法将在整個請求完成之後,也就是說在視圖渲染之後進行調用,主要用于進行一些資源的釋放 

    public void aftercompletion(webrequest request, exception exception)  

        system.out.println(exception + "-=-=--=--=-=-=-=-=-=-=-=-==-=--=-=-=-=");  

SpringMVC中使用Interceptor攔截器   一、定義Interceptor實作類   二、把定義的攔截器類加到SpringMVC的攔截體系中

    xmlns:mvc="http://www.springframework.org/schema/mvc"  

    xsi:schemalocation=" http://www.springframework.org/schema/mvc  

        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"  

         下面是我的聲明示例:

SpringMVC中使用Interceptor攔截器   一、定義Interceptor實作類   二、把定義的攔截器類加到SpringMVC的攔截體系中

<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"  

    xsi:schemalocation="http://www.springframework.org/schema/beans  

     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  

     http://www.springframework.org/schema/context  

     http://www.springframework.org/schema/context/spring-context-3.0.xsd  

     http://www.springframework.org/schema/mvc  

     http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  

         這樣在springmvc的配置檔案中就可以使用mvc标簽了,mvc标簽中有一個mvc:interceptors是用于聲明springmvc的攔截器的。

SpringMVC中使用Interceptor攔截器   一、定義Interceptor實作類   二、把定義的攔截器類加到SpringMVC的攔截體系中

<mvc:interceptors>  

    <!-- 使用bean定義一個interceptor,直接定義在mvc:interceptors根下面的interceptor将攔截所有的請求 -->  

    <bean class="com.host.app.web.interceptor.allinterceptor"/>  

    <mvc:interceptor>  

        <mvc:mapping path="/test/number.do"/>  

        <!-- 定義在mvc:interceptor下面的表示是對特定的請求才進行攔截的 -->  

        <bean class="com.host.app.web.interceptor.logininterceptor"/>  

    </mvc:interceptor>  

</mvc:interceptors>  

          由上面的示例可以看出可以利用mvc:interceptors标簽聲明一系列的攔截器,然後它們就可以形成一個攔截器鍊,攔截器的執行順序是按聲明的先後順序執行的,先聲明的攔截器中的prehandle方法會先執行,然而它的posthandle方法和aftercompletion方法卻會後執行。

          在mvc:interceptors标簽下聲明interceptor主要有兩種方式:

                    (1)直接定義一個interceptor實作類的bean對象。使用這種方式聲明的interceptor攔截器将會對所有的請求進行攔截。

                    (2)使用mvc:interceptor标簽進行聲明。使用這種方式進行聲明的interceptor可以通過mvc:mapping子标簽來定義需要進行攔截的請求路徑。

          經過上述兩步之後,定義的攔截器就會發生作用對特定的請求進行攔截了。