輕量級JavaEE企業應用實戰(十八)

詳解Struts2的攔截器機制

Struts2攔截器是可插拔式的設計:如果需要使用某個攔截器,只需要在配置文件中應用該攔截器即可;如果不需要,則不需要在配置文件中配置;

攔截器在Struts2中的作用

對於任何MVC框架,他們都會完成一些通用的邏輯控制、例如:解析請求參數、類型轉換,將請求參數封裝成DTO,執行輸入校驗,解析文件上傳表單中的文件域等;
早期的Struts1把這些動作寫在覈心控制器裏,缺點:
靈活性非常差:強制所有項目都必須使用該框架提供的全部功能,無論是否需要,核心控制器總會完成這些操作
可擴展性很差:如果需要讓核心控制器完成更多自定義的處理,需要擴展可信控制器;
Struts2:把大部分核心控制器需要完成的工作按功能分開定義,每個攔截器完成一個功能,這些攔截器自由選擇,靈活組合;絕大多數功能是通過這些攔截器來完成的,當StrutsPrepareAndExecuteFilter攔截到用戶請求之後,大量攔截器會對請求進行處理,然後纔會調用用戶開發的Action實例進行處理

Struts2內建的攔截器

這些攔截器配置在struts-default.xml中,如果我們定義的package繼承了struts-default包,就可以自由使用這些攔截器,否則需要自行定義;

配置攔截器
<interceptor name="攔截器名" class="攔截器實現類" />

<interceptor name="攔截器名" class="實現類">
    <param name="參數名">參數值</param>
</interceptor>

配置攔截器棧:可配置多個
<interceptor-stack>
    <interceptor-ref name="攔截器名" />
</interceptor-stack>

配置默認攔截器

當配置一個包時,可以配置其指定默認攔截器。一旦某個包指定了默認攔截器,Action中沒有顯式指定攔截器,則默認攔截器會起作用;如果一旦爲包中的Action顯式應用了某個攔截器,則默認攔截器失效;如果該Action需要默認攔截器,必須手動添加該攔截器的引用

<package name="包名">
    <interceptors>
        <interceptor .../>
        <interceptor-stack .../>
    </interceptors>
    <default-interceptor-ref name="攔截器名或攔截器棧名" />
    <action .../>
</package>
注:每個包只能定義一個默認攔截器;如果需要多個攔截器共同作爲默認攔截器,可以將這些攔截器配置成攔截器棧,然後把該攔截器棧配置成默認攔截器

實現攔截器類

開發自己的攔截器,需要實現com.opensymphony.xwork2.interceptor.Interceptor類

public interceptor Interceptor extends Serializable {
    void destory();
    void init();
    String intercept(ActionInvocation invocation) throws exception;
}

此外,還實現了一個AbstractInterceptor類,已經實現了destory和init方法,所以只需要繼承AbstractInterceptor,實現更加簡單

public class SimpleInterceptor extends AbstractInterceptor {
    private String name;
    ...
    public String intercept(ActionInvocation invocation) 
        throws Exception {
        LoginAction action = (LoginAction)invocation.getAction();
        long start = System.currentTimeMillis();
        //執行該攔截器的後一個攔截器,如果沒有,則執行execute方法
        String result = invocation.invoke();
        long end = System.currentTimeMillis();
    }
}

攔截方法的攔截器

public class MyFilterInterceptor extends MethodFilterInterceptor {
    private String name;
    ...
    public String doInterceptor(ActionInvocation invocation) 
        throws Exception {
        LoginAction action = (LoginAction)invocation.getAction();
        long start = System.currentTimeMillis();
        //執行該攔截器的後一個攔截器,如果沒有,則執行execute方法
        String result = invocation.invoke();
        long end = System.currentTimeMillis();
    }
}

重寫的是:doInterceptor方法,繼承的是MethodFilterInterceptor
原因:MethodFilterInterceptor是AbstractInterceptor的子類,實現了intercept方法,提供了一個doInterceptor抽象方法;可以說已經實現了對Action的攔截行爲,但真正的邏輯需要重寫doInterceptor來實現;

<interceptors>
    <interceptor name="mysimple" class="com.interceptor.
        MyFilterInterceptor">
        <param name="name">..</param>
    </interceptor>
</interceptors>

<action name="login" class="com.action.LoginAction">
    <result name="error">error.jsp</result>
    ..
    <interceptor-ref name="defaultStack" />
    <interceptor-ref name="mysimple">
        <param name="excludeMethods">execute,test</param>
        <param name="includeMethods">execute</param>
    </interceptor-ref>
</action>

excludeMethods參數指定:execute和test方法不需要被攔截,又通過includeMethods參數指定execute方法需要攔截;
兩者衝突,以includeMethods參數指定的爲準,即execute被攔截

Struts2中提供了這種過濾的攔截器有幾個:
TokenInterceptor
TokenSessionStoreInterceptor
DefaultWorkflowInterceptor
ValidationInterceptor

攔截器執行順序

在Action的控制方法執行之前,位於攔截器鏈前邊的攔截器將先發生作用,在Action的控制方法執行後,位於攔截器鏈前邊的攔截器後發生作用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章