struts2攔截器簡介

1、理解Struts2攔截器html

1. Struts2攔截器是在訪問某個Action或Action的某個方法,字段以前或以後實施攔截,而且Struts2攔截器是可插拔的,攔截器是AOP的一種實現.java

2. 攔截器棧(Interceptor Stack)。Struts2攔截器棧就是將攔截器按必定的順序聯結成一條鏈。在訪問被攔截的方法或字段時,Struts2攔截器鏈中的攔截器就會按其以前定義的順序被調用。spring

2、實現Struts2攔截器原理apache

Struts2攔截器的實現原理相對簡單,當請求struts2的action時,Struts 2會查找配置文件,並根據其配置實例化相對的    攔截器對象,而後串成一個列表,最後一個一個地調用列表中的攔截器編程

3、定義Struts2攔截器。設計模式

Struts2規定用戶自定義攔截器必須實現com.opensymphony.xwork2.interceptor.Interceptor接口。該接口聲明瞭3個方法, 安全

 

void init();cookie

void destroy();session

String intercept(ActionInvocation invocation) throws Exception;app

 

其中,init和destroy方法會在程序開始和結束時各執行一遍,無論使用了該攔截器與否,只要在struts.xml中聲明瞭該Struts2攔截器就會被執行。

intercept方法就是攔截的主體了,每次攔截器生效時都會執行其中的邏輯。

不過,struts中又提供了幾個抽象類來簡化這一步驟。

 

public abstract class AbstractInterceptor implements Interceptor;

public abstract class MethodFilterInterceptor extends AbstractInterceptor;

 

都是模板方法實現的。

其中AbstractInterceptor提供了init()和destroy()的空實現,使用時只須要覆蓋intercept()方法;

而MethodFilterInterceptor則提供了includeMethods和excludeMethods兩個屬性,用來過濾執行該過濾器的action的方法。能夠經過param來加入或者排除須要過濾的方法。

通常來講,攔截器的寫法都差很少。看下面的示例:

 

package interceptor;

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.interceptor.Interceptor;

public class MyInterceptor implements Interceptor {

public void destroy() {

// TODO Auto-generated method stub

}

public void init() {

// TODO Auto-generated method stub

}

public String intercept(ActionInvocation invocation) throws Exception {

System.out.println("Action執行前插入 代碼");     

//執行目標方法 (調用下一個攔截器, 或執行Action)   

final String res = invocation.invoke();   

System.out.println("Action執行後插入 代碼");   

return res;   

}

}

4、配置Struts2攔截器

Struts2攔截器須要在struts.xml中聲明,以下struts.xml配置文件

 

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<constant name="struts.objectFactory" value="spring" />

<package name="default" extends="struts-default">

<interceptors>

<interceptor name="MyInterceptor" class="interceptor.MyInterceptor"></interceptor>

<interceptor-stack name="myInterceptorStack">

<interceptor-ref name="MyInterceptor"/>

<interceptor-ref name="defaultStack"/>

</interceptor-stack>

</interceptors>

<action name="loginAction" class="loginAction">

<result name="fail">/index.jsp </result>

<result name="success">/success.jsp</result>

<interceptor-ref name="myInterceptorStack"></interceptor-ref>

</action>

</package>

</struts>

 

攔截器

 

名字

 

說明

 

Alias Interceptor

 

alias

 

在不一樣請求之間將請求參數在不一樣名字件轉換,請求內容不變

 

Chaining Interceptor

 

chain

 

讓前一個Action的屬性能夠被後一個Action訪問,如今和chain類型的result()結合使用。

 

Checkbox Interceptor

 

checkbox

 

添加了checkbox自動處理代碼,將沒有選中的checkbox的內容設定爲false,而html默認狀況下不提交沒有選中的checkbox。

 

Cookies Interceptor

 

cookies

 

使用配置的name,value來是指cookies

 

Conversion Error Interceptor

 

conversionError

 

將錯誤從ActionContext中添加到Action的屬性字段中。

 

Create Session Interceptor

 

createSession

 

自動的建立HttpSession,用來爲須要使用到HttpSession的攔截器服務。

 

Debugging Interceptor

 

debugging

 

提供不一樣的調試用的頁面來展示內部的數據情況。

 

Execute and Wait Interceptor

 

execAndWait

 

在後臺執行Action,同時將用戶帶到一箇中間的等待頁面。

 

Exception Interceptor

 

exception

 

將異常定位到一個畫面

 

File Upload Interceptor

 

fileUpload

 

提供文件上傳功能

 

I18n Interceptor

 

i18n

 

記錄用戶選擇的locale

 

Logger Interceptor

 

logger

 

輸出Action的名字

 

Message Store Interceptor

 

store

 

存儲或者訪問實現ValidationAware接口的Action類出現的消息,錯誤,字段錯誤等。

 

Model Driven Interceptor

 

model-driven

 

若是一個類實現了ModelDriven,將getModel獲得的結果放在Value Stack中。

 

Scoped Model Driven

 

scoped-model-driven

 

若是一個Action實現了ScopedModelDriven,則這個攔截器會從相應的Scope中取出model調用Action的setModel方法將其放入Action內部。

 

Parameters Interceptor

 

params

 

將請求中的參數設置到Action中去。

 

Prepare Interceptor

 

prepare

 

若是Acton實現了Preparable,則該攔截器調用Action類的prepare方法。

 

Scope Interceptor

 

scope

 

將Action狀態存入session和application的簡單方法。

 

Servlet Config Interceptor

 

servletConfig

 

提供訪問HttpServletRequest和HttpServletResponse的方法,以Map的方式訪問。

 

Static Parameters Interceptor

 

staticParams

 

從struts.xml文件中將ION>中的

中的內容設置到對應的Action中。

 

Roles Interceptor

 

roles

 

肯定用戶是否具備JAAS指定的Role,不然不予執行。

 

Timer Interceptor

 

timer

 

輸出Action執行的時間

 

Token Interceptor

 

token

 

經過Token來避免雙擊

 

Token Session Interceptor

 

tokenSession

 

和Token Interceptor同樣,不過雙擊的時候把請求的數據存儲在Session中

 

Validation Interceptor

 

validation

 

使用action-validation.xml文件中定義的內容校驗提交的數據。

 

Workflow Interceptor

 

workflow

 

調用Action的validate方法,一旦有錯誤返回,從新定位到INPUT畫面

 

Parameter Filter Interceptor

 

N/A

 

從參數列表中刪除沒必要要的參數

 

Profiling Interceptor

 

profiling

 

經過參數激活profile

 

提到攔截器,使我不得不想起武俠劇中劫匪們常說的一句話:「此山是我開,此樹是我栽,要打此路過,留下買路財!」。難不成程序中也有「打劫」的,說的沒錯,攔截器就是個打劫的。在現實生活中,劫匪劫的大都是錢財,固然也有別的什麼,那麼程序中的「劫匪」劫的又是什麼呢?或者說程序中爲何須要它?在咱們的平常編程中少不了寫一些重複的代碼,例如在一個地方中寫了一段代碼,後來發現這段代碼在其它地方中一樣須要,在傳統的編程中咱們必定會採起復制、粘貼的辦法。若是這段代碼只在這一兩個處須要,咱們採起這種辦法,還說的過去,可是若是系統對這段代碼過於依賴,也就是這段代碼在系統中出現的過多,若是那一天咱們發現這段代碼中在某些地方還須要完善,咱們是否是要着個修改它們呢?我估計沒有人會這麼作,它嚴重違反了軟件開發中一條很是重要的DRY規則,不寫重複代碼。說了這麼多你必定知道咱們爲何須要在程序中弄一個「劫匪」了吧。這個「劫匪」就是並非劫取什麼東西,只是爲了在某個程序執行先後,動態的增長一些功能(之前所寫通用代碼塊)或進行一些檢查工做。那麼這個攔截器究竟是怎麼實現的呢?實際上它是用Java中的動態代理來實現的,具體能夠參考《設計模式學習筆記(十六)—Proxy模式》。

2、攔截器在Struts2中的應用

對於Struts2框架而言,正是大量的內置攔截器完成了大部分操做。像params攔截器將http請求中參數解析出來賦值給Action中對應的屬性。Servlet-config攔截器負責把請求中HttpServletRequest實例和HttpServletResponse實例傳遞給Action……struts2內置的攔截器有不少,在此我就不一一列舉了,具體能夠參考《Struts2中有關struts-default.xml,struts.xml,struts.properties文件詳解》。

那麼怎麼在struts2中定義本身的攔截器呢?

很簡單Struts2爲咱們提供了一個Interceptor接口,該接口源代碼以下:

publicinterface Interceptor extends Serializable {

    void destroy();

    void init();

    String intercept(ActionInvocation invocation) throws Exception;

}

1)    init():在攔截器執行以前調用,主要用於初始化系統資源。

2)    destroty():與init()對應,用於攔截器執行以後銷燬資源。

3)    intercept():攔截器的核心方法,實現具體的攔截操做。與action同樣,該方法也返回一個字符串做爲邏輯視圖。若是攔截器成功調用了action,則返回一個真正的,也就是該action中execute()方法返回的邏輯視圖,反之,則返回一個自定義的邏輯視圖。

一般咱們使用攔截器並不須要申請資源,爲此Struts2還爲咱們提供了一個AbstractInterceptor類,該類的init()和destroy()都是空實現。咱們開發本身的攔截器只須要繼承這個類就好了。

下面建立一個判斷用戶是否登陸的攔截器。代碼以下:


struts.xml中配置一下。

/** *//**
 *
 * @author <a href="flustarmailto:flustar2008@163.com">flustar</a>
 * @version 1.0
 * Creation date: Feb 12, 2008 5:05:28 PM
 */

import java.util.Map;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

@SuppressWarnings("serial")
public class CheckLoginInterceptor extends AbstractInterceptor {

    @SuppressWarnings("unchecked")
    public String intercept(ActionInvocation actionInvocation) throws Exception {
         System.out.println("begin check login interceptor!");

            // 檢查Session中是否存在user

            Map session = actionInvocation.getInvocationContext().getSession();

            String username = (String) session.get("user");

            if (username != null && username.length() > 0) {

                // 存在的狀況下進行後續操做。

                System.out.println("already login!");

                return actionInvocation.invoke();

            } else {

                // 不然終止後續操做,返回LOGIN

                System.out.println("no login, forward login page!");

                return Action.LOGIN;

            }

        }


    }

 

建立好攔截器後,還不能使用,還須要咱們在

下面看一下怎麼配置攔截器。

<interceptors>

           <interceptor name="checkLogin" class="com.myblog.interceptor.CheckLoginInterceptor" />

</interceptors>

這個定義好的攔截器在Action中怎麼使用呢?使用方法很簡單,以下:

<action name=" " class=" " >

           <result> </result>

           <interceptor-ref name="checkLogin" />

</action>

一旦咱們爲某個action引用了自定義的攔截器,struts2默認的攔截器就不會再起做用,所以還須要引用默認攔截器。

<action name=" " class=" " >

           <result> </result>

           <interceptor-ref name="checkLogin" />

                     <interceptor-ref name="defaultStack" />

</action>

可是咱們這麼作彷佛也不太方便,由於若是攔截器checkLogin須要被多個action引用的話,每個都要配置一遍太麻煩了。咱們能夠把它定義成默認的攔截器。

<interceptors>

           <interceptor name="checkLogin" class="com.myblog.interceptor.CheckLoginInterceptor" />

           <!—-定義一個攔截器棧-->

           <interceptor-stack name="mydefault">

              <interceptor-ref name="defaultStack" />

              <interceptor-ref name="checkLogin" />

           </interceptor-stack>

</interceptors>

<default-interceptor-ref name="mydefault" />

另外,struts2還爲咱們提供了一個方法過濾的攔截器MethodFilterInterceptor類,該類繼承AbstractInterceptor類,重寫了intercept(ActionInvocation invocation)並提供了一個新的方法doInterceptor(ActionInvocation invocation)抽象方法。該類的使用方法很簡單,就不舉例了。這個攔截器與以往的攔截器配置有所不一樣。那就是能夠指定哪些方法須要被攔截,那些不須要。一般在引用該攔截器時指定。

<interceptor-ref name="  ">

       <param name="exculdeMethods"></param>

       <param name="includeMethods"></param>    

</interceptor-ref>

exculdeMethods:是不被攔截的方法,若是有多個以逗號分隔。

includeMethods:須要被攔截的方法,若是有多個以逗號分隔。

 

 

 

 

 

 

 

 

攔截器-Exception
<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>

配置Exception,若是出現什麼樣的異常就跳轉到對應的頁面。

在action執行以後,拋出異常纔會被調用的。

攔截器alias
在action執行以前執行

The aim of this Interceptor is to alias a named parameter to a different named parameter. By acting as the glue between actions sharing similiar parameters (but with different names), it can help greatly with action chaining.

 

主要用在chain的action,若是從一個action直接跳轉到另一個action,可能須要傳遞參數值,而參數的名稱是不同的,這個時候alias攔截器就起做用了。

攔截器-ServletConfig
在action執行以前執行

 

An interceptor which sets action properties based on the interfaces an action implements. For example, if the action implements ParameterAware then the action context's parameter map will be set on it.

配置了這個攔截器後,action能夠實現某些接口,就能夠自動獲取到某些對象,例如request和response對象。

詳細的例子:com.work.core.action.OurActionSupport

攔截器-prepare
在action執行以前執行

必須實現Preparable接口,com.opensymphony.xwork2.Preparable

<interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>

 

能夠經過setAlwaysInvokePrepare方法,來決定prepare()是否要被執行。

和validate方法同樣,你能夠在action中設定prepareList()方法,那麼這個方法就會被首先執行,而後在執行prepare方法。(prepareDoList也能夠)。

先執行prepareList若是這個找不到就尋找prepareDoList方法,若是都找不到就不執行。

須要測試。

(注意:須要使用呢params prepare params 攔截器的配置方式)

Prepare方法,當前action中的任何方法執行都會執行到他;

import com.opensymphony.xwork2.Preparable;

    public void prepare() throws Exception {

       if(log.isInfoEnabled())

           log.info("執行prepare()方法了");    

    }

    /**

     * 測試失敗!

     * @throws Exception

     */

    public void prepareLoadForEdit() throws Exception {

       if(log.isInfoEnabled())

           log.info("執行prepareLoadForEdit()方法了");

       try {

           if (labid == null) {

              //lab = null;

              log.debug("labid==null");

           } else {

              lab = labServiceDao.loadForEditById(labid);

              log.debug("lab="+lab);

           }

       } catch (DataAccessException e) {

           if (log.isErrorEnabled()) {

              log.error("根據labid"+labid+"查詢出錯。", e);

           }

       }

      

    }  

攔截器-i18n
在action執行以前執行

 

<interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>

 

實現國際化的功能。

 

攔截器-chain
在action執行以前執行

若是action實現了接口com.opensymphony.xwork2.Unchainable,那麼對應的屬性將再也不拷貝。

An interceptor that copies all the properties of every object in the value stack to the currently executing object, except for any object that implements Unchainable. A collection of optional includes and excludes may be provided to control how and which parameters are copied. Only includes or excludes may be specified. Specifying both results in undefined behavior. See the javadocs for OgnlUtil.copy(Object, Object, java.util.Map, java.util.Collection, java.util.Collection) for more information.

It is important to remember that this interceptor does nothing if there are no objects already on the stack. This means two things: One, you can safely apply it to all your actions without any worry of adverse affects. Two, it is up to you to ensure an object exists in the stack prior to invoking this action. The most typical way this is done is through the use of the chain result type, which combines with this interceptor to make up the action chaining feature.

 

攔截器- scopedModelDriven
在action執行以前執行

你的action實現com.opensymphony.xwork2.interceptor. ScopedModelDriven接口;

若是一個Action實現了ScopedModelDriven,則這個攔截器會從相應的Scope中取出model調用Action的setModel方法將其放入Action內部。

 

攔截器- modelDriven
在action執行以前執行

實現ModelDriven接口

Watches for ModelDriven actions and adds the action's model on to the value stack.

Note: The ModelDrivenInterceptor must come before the both StaticParametersInterceptor and ParametersInterceptor if you want the parameters to be applied to the model.

 

攔截器- fileUpload
上傳文件的代碼,在action執行以前執行,清除臨時文件在action以後執行。

 

<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>

 

 

攔截器- checkbox(還須要測試,不是很明白)
在action執行以前執行

org.apache.struts2.interceptor.CheckboxInterceptor

 

若是使用了checkbox標籤,才使用這個吧?

 

這個攔截器的功能比較奇怪啊,看了源代碼,也不明白爲何要將checkbox沒有選中的設置爲false。

    public String intercept(ActionInvocation ai) throws Exception {

        Map parameters = ai.getInvocationContext().getParameters();

        Map<String, String> newParams = new HashMap<String, String>();

        Set<String> keys = parameters.keySet();

        for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {

            String key = iterator.next();

 

            if (key.startsWith("__checkbox_")) {

                String name = key.substring("__checkbox_".length());

 

                iterator.remove();

 

                // is this checkbox checked/submitted?

                if (!parameters.containsKey(name)) {

                    // if not, let's be sure to default the value to false

                    newParams.put(name, uncheckedValue);

                }

            }

        }

 

        parameters.putAll(newParams);

 

        return ai.invoke();

}

 

設置checkbox標籤不被選中的時候的默認值

<interceptor-ref name="checkbox">
          <param name="uncheckedValue">0</param>
       </interceptor-ref>

攔截器- staticParams
在action執行以前執行

 

<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>

This interceptor populates the action with the static parameters defined in the action configuration. If the action implements Parameterizable, a map of the static parameters will be also be passed directly to the action.

 

在struts的xml配置文件中配置的參數

攔截器-params
在action執行以前執行

 

<interceptor name="params"

class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>

將全部的參數值放入到stack中去。(Ognl)

ParameterNameAware接口

com.opensymphony.xwork2.interceptor.ParameteraNameAware

實現了此接口,能夠設定容許哪些action的屬性的值被放入stack中去。

 

攔截器-conversionError
在action執行以前執行

轉換器

<interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>

將錯誤從ActionContext中添加到Action的屬性字段中

 

攔截器- validation(xml自動校驗配置文件)
在action執行以前執行

使用action-validation.xml文件中定義的內容校驗提交的數據。

 

攔截器-workflow(執行action中的validate方法)
在action執行以前執行

 

調用Action的validate方法,一旦有錯誤返回,從新定位到INPUT畫面

<interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>

和prepare攔截器相似啊

順序查找並執行下面的方法。

ValidateSave  validateDoSave  validate 

 

===攔截器必須是線程安全的==========================
攔截器-cookie
將cookie的值,放到valuestack中去,

你也能夠實現接口CookiesAware,在程序中編程設置。

 

攔截器- createSession
org.apache.struts2.interceptor.CreateSessionInterceptor

 

This interceptor creates the HttpSession.

This is particular usefull when using the <@s.token> tag in freemarker templates. The tag do require that a HttpSession is already created since freemarker commits the response to the client immediately.

攔截器-其餘
Debugging Interceptor
 debugging
 提供不一樣的調試用的頁面來展示內部的數據情況。
 
Execute and Wait Interceptor
 execAndWait
 在後臺執行Action,同時將用戶帶到一箇中間的等待頁面。
 
Message Store Interceptor
 store
 存儲或者訪問實現ValidationAware接口的Action類出現的消息,錯誤,字段錯誤等。
 
Scope Interceptor
 scope
 將Action狀態存入session和application的簡單方法。
 
Roles Interceptor
 roles
 肯定用戶是否具備JAAS指定的Role,不然不予執行。
 
Token Interceptor
 token
 經過Token來避免雙擊
 
Token Session Interceptor
 tokenSession
 和Token Interceptor同樣,不過雙擊的時候把請求的數據存儲在Session中
 
Parameter Filter Interceptor
 N/A
 從參數列表中刪除沒必要要的參數
 
Profiling Interceptor
 profiling
 經過參數激活profile
 

 

 

在攔截器中獲取action的屬性值
// 找到對應的臨時文件的路徑

       String tempFilePath = (String) invocation.getStack().findValue(

              "tempFilePath");

 

給攔截器棧中的某個攔截器配置參數的方法
<!DOCTYPE xwork PUBLIC

        "-//OpenSymphony Group//XWork 1.1.1//EN"

        "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd"

        >

 

<xwork>

    <include file="xwork-test-beans.xml" />

    <package name="default">

        <interceptors>

            <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>

            <interceptor name="test" class="com.opensymphony.xwork2.mock.MockInterceptor">

                <param name="foo">fooDefault</param>

            </interceptor>

 

            <interceptor-stack name="defaultStack">

                <interceptor-ref name="timer"/>

                <interceptor-ref name="test"/>

            </interceptor-stack>

        </interceptors>

 

        <default-interceptor-ref name="defaultStack" />

 

        <action name="TestInterceptorParam" class="com.opensymphony.xwork2.SimpleAction">

            <interceptor-ref name="defaultStack">

                <param name="test.expectedFoo">expectedFooValue</param>

            </interceptor-ref>

        </action>

 

        <action name="TestInterceptorParamOverride" class="com.opensymphony.xwork2.SimpleAction">

            <interceptor-ref name="defaultStack">

                <param name="test.foo">foo123</param>

                <param name="test.expectedFoo">expectedFooValue2</param>

            </interceptor-ref>

           defaultStack中有個攔截器的名稱爲test,test攔截器中有配置參數的get和set方法。

        </action>

    </package>

 

</xwork>

相關文章
相關標籤/搜索