攔截器原理(AOP、責任鏈模式、攔截器的創建、自定義攔截器)


1、Struts2攔截器概述:

(1)Struts2框架封裝中封裝了很多功能,這些功能其實都是封裝在Struts2的攔截器里面,Struts2里面有很多攔截器,每次不是這些攔截器都執行,每次只執行默認的攔截器。

(2)Struts2默認攔截器的位置:

 

 (3)攔截器在Action對象創建之后,action的方法執行之前執行。

 

2、Struts2底層原理:

(1)原理一(AOP思想):

AOP:面向切面(方面)編程,不通過修改源代碼的方式來擴展功能。

 

在上面的登錄流程圖中,如果在登錄成功后要添加用戶的權限判斷功能,不需要修改源代碼。

(2)責任鏈模式(和過濾鏈模式思想相似):

過濾鏈模式:一個請求需要經過多個過濾器,而每個過濾器只有經過放行操作后才能進行下一步操作。

責任鏈模式:例如執行:添加、刪除、修改操作,先執行添加操作,添加操作執行結束之后執行刪除操作(類似於過濾鏈模式中的放行操作),執行刪除操作之后執行修改操作。

 

3、AOP思想和責任鏈模式在Struts2中的應用:

(1)攔截器在Action對象創建之后,action的方法執行之前執行(在Action方法執行之前執行默認攔截器,執行過程中使用AOP思想,在Action中沒有直接調用攔截器的方法,而是使用配置文件的方式進行操作)。

(2)如果攔截器執行過程中有多個攔截器則采用責任鏈模式進行,如果有三個攔截器,則先執行攔截器一,執行一之后做放行操作,然后執行攔截器二,做放行操作,最后執行攔截器三,放行后,執行Action方法。

 

 

4、過濾器和攔截器的區別:

(1)過濾器:過濾器理論上可以過濾任何內容,例如:圖片、html、jsp、servlet的路徑。

(2)攔截器:攔截器只能攔截Action。

 

5、servlet和action的區別:

(1)servlet:只在首次訪問的時候創建,只創建一次(單實例對象)

(2)action:每次訪問的時候創建,可以創建多次(多實例對象)

 

6、生命周期:

隨項目的啟動而創建,隨項目的關閉而銷毀。

 

7、攔截器的創建方法

(1)方法一:實現接口(需要實現三個方法,不推薦)

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class InterceptorDemo implements Interceptor {
    @Override
    public void destroy() {
        
    }

    @Override
    public void init() {

    }

    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        return null;
    }
}

(2)方法二:繼承AbstractInterceptor類,因為該類已經實現了Interceptor接口,因此較為方便(幫我們實現了init和destory方法,就可以只實現intercept方法):

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class InterceptorDemo1 extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        return null;
    }
}

(3)方法三:

public class InterceptorDemo2 extends MethodFilterInterceptor {
    @Override
    protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
        actionInvocation.invoke();//放行
        return null;
    }
}

調用invoke()之前的代碼叫做前處理,之后的代碼叫做后處理。要是不想放行只需要返回一個字符串即可(不調用invoke()方法)。這樣就不會執行后續的攔截器和Action,直接交給Result處理結果。

 

8、攔截器的配置

(1)先查看系統對攔截器的配置:

指明攔截器類:

<interceptors>
            <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
            <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>

默認攔截器棧(20個攔截器):

 <interceptor-stack name="defaultStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>

指定默認攔截器棧:

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

        <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />

(2)按照以上步驟配置自定義攔截器(在struts.xml文件中進行配置):

<struts>
    <package name="action" namespace="/a" extends="struts-default">
        <interceptors>
        <interceptor name="MyInter" class="pers.zhb.interceptor.InterceptorDemo2"/>
        <interceptor-stack name="MyStack">
            <interceptor-ref name="MyInter"></interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref><!--引入默認的20個攔截器-->
        </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="MyStack"></default-interceptor-ref>
        <action name="Demo1" class="pers.zhb.interceptor.InterceptorDemo1" method="execute">
            <result name="success" type="dispatcher">/hello.jsp</result>
        </action>
    </package>
</struts>

配置攔截器共分為三個步驟:注冊攔截器、注冊攔截器棧、指定默認攔截器。在注冊攔截器棧的時候需要將自己配置的攔截器放到系統的20個攔截器前面,這樣可以保證攔截器的錯誤處理功能,以便在自定義攔截器出現錯誤的時候后面的攔截器作出處理。

創建一個Action,調用自定義的攔截器:

public class InterceptorDemo1 extends ActionSupport {
    public String execute(){
        System.out.println("我是調用攔截器的Action!");
        return "success";
    }
}

創建攔截器:

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class InterceptorDemo2 extends MethodFilterInterceptor {
    @Override
    protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
        System.out.println("前處理");
        actionInvocation.invoke();//放行
        System.out.println("后處理");
        return null;
    }
}

其中invoke()方法可以調用攔截器。

測試結果:

 

 

 

 

 

9、對方法攔截的指定(即指定Action中哪些方法調用攔截器,哪些方法不調用攔截器)

(1)指定哪些方法不調用攔截器

struts.xml配置文件:

<package name="action" namespace="/a" extends="struts-default">
        <interceptors>
        <interceptor name="MyInter" class="pers.zhb.interceptor.InterceptorDemo2"/>
        <interceptor-stack name="MyStack">
            <interceptor-ref name="MyInter">
                <param name="excludeMethods">add</param>
            </interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref><!--引入默認的20個攔截器-->
        </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="MyStack"></default-interceptor-ref>
        <action name="Demo1_*" class="pers.zhb.interceptor.InterceptorDemo1" method="{1}">
            <result name="success" type="dispatcher">/hello.jsp</result>
        </action>
    </package>

這里執行Action時用到了動態方法調用,畫橫線的一行指定了add方法不調用攔截器。

Action:

public class InterceptorDemo1 extends ActionSupport {
    public String add(){
        System.out.println("ADD");
        return null;
    }
    public String delete(){
        System.out.println("DELETE");
        return null;
    }
    public String update(){
        System.out.println("UPDATE");
        return null;
    }
    public String selete(){
        System.out.println("SELETE");
        return null;
    }
    public String execute(){
        System.out.println("我是調用攔截器的Action!");
        return "success";
    }
}

此Action中定義了四個方法,通過配置文件來指定哪些方法調用攔截器,哪些方法不調用攔截器。

調用攔截器的類:

public class InterceptorDemo2 extends MethodFilterInterceptor {
    @Override
    protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
        System.out.println("前處理");
        actionInvocation.invoke();//放行
        System.out.println("后處理");
        return null;
    }
}

運行結果:

 

 調用Action中的add方法時未調用攔截器。

(2)指定哪些方法攔截:

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

 

 只需修改配置文件中的如上的配置,上面的配置為:指定add方法調用攔截器,其他方法不調用攔截器。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM