<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    旅行的意義

     

    Struts2的攔截器

    struts2的攔截器(Interceptor)是struts中比較復(fù)雜也比較核心的內(nèi)容,功能挺強(qiáng)大。不過(guò)對(duì)于這種很難很強(qiáng)大的東東,一般還是比較抵觸的:畢竟學(xué)起來(lái)比較艱深,學(xué)完了有沒(méi)有用又另當(dāng)別論了——那為什么還要學(xué)呢?
    如果不能解決實(shí)際問(wèn)題,它吹得再牛,也不見(jiàn)得有多好。所以,攔截器到底做什么的呢?

    攔截器的一個(gè)最廣泛的應(yīng)用是全局訪問(wèn)權(quán)限控制。


    在做網(wǎng)站的時(shí)候,一般來(lái)說(shuō)都有全局的權(quán)限控制這一塊。如果在每個(gè)頁(yè)面的前頭加一段代碼的話,頁(yè)面少還問(wèn)題不大,頁(yè)面多了維護(hù)起來(lái)就比較恐怖了。Struts中提供了一種全局性的解決方案:攔截器。

    攔截器的底層實(shí)現(xiàn)機(jī)制還是AOP,其原理是……AOP的實(shí)現(xiàn)原理就不說(shuō)了,攔截器的原理是在特定函數(shù)的執(zhí)行前后,插入自定義方法,具體到對(duì)Action攔截器中,就是每個(gè)(或者每個(gè)指定的)Action的Execute()或者其他指定方法執(zhí)行前后,插入自定義的方法。

    也就是說(shuō),你可以在(除了登錄Action本身之外)所有Action邏輯發(fā)生之前,插入一段用戶驗(yàn)證邏輯,從而將繞過(guò)登錄界面的用戶請(qǐng)求擋在核心業(yè)務(wù)邏輯之外;進(jìn)一步的,可以將各種業(yè)務(wù)按照權(quán)限分級(jí)分類(lèi),使用不同的攔截器邏輯進(jìn)行攔截,從而達(dá)到多級(jí)權(quán)限控制的效果。


    上面說(shuō)的只是攔截器的一部分功能,其實(shí)struts自己也預(yù)定義了許多攔截器,比如說(shuō)。Action映射、參數(shù)解析、日志、國(guó)際化 、驗(yàn)證……struts中許多非常核心的功能其實(shí)都是通過(guò)攔截器機(jī)制來(lái)實(shí)現(xiàn)的。如果有興趣了解,struts2-core-xxx.jar中struts-default.xml的<interceptors>節(jié)點(diǎn)可以作為起點(diǎn),其中定義了struts內(nèi)建的所有攔截器。


    下面簡(jiǎn)單記錄實(shí)現(xiàn)步驟
    1、定義攔截器。

    Struts2規(guī)定用戶自定義攔截器必須實(shí)現(xiàn)com.opensymphony.xwork2.interceptor.Interceptor接口
    。該接口聲明了3個(gè)方法,

    void init();
    void destroy();
    String intercept(ActionInvocation invocation) 
    throws Exception;

    其中,init和destroy方法會(huì)在程序開(kāi)始和結(jié)束時(shí)各執(zhí)行一遍,不管使用了該攔截器與否,只要在struts.xml中聲明了該攔截器就會(huì)被執(zhí)行。
    intercept方法就是攔截的主體了,每次攔截器生效時(shí)都會(huì)執(zhí)行其中的邏輯。

    不過(guò),struts中又提供了幾個(gè)抽象類(lèi)來(lái)簡(jiǎn)化這一步驟。
    public abstract class AbstractInterceptor implements Interceptor;
    public abstract class MethodFilterInterceptor extends AbstractInterceptor;
    都是模板方法實(shí)現(xiàn)的。
    其中AbstractInterceptor提供了init()和destroy()的空實(shí)現(xiàn),使用時(shí)只需要覆蓋intercept()方法;
    MethodFilterInterceptor則提供了includeMethods和excludeMethods兩個(gè)屬性,用來(lái)過(guò)濾執(zhí)行該過(guò)濾器的action的方法。可以通過(guò)param來(lái)加入或者排除需要過(guò)濾的方法。

    一般來(lái)說(shuō),攔截器的寫(xiě)法都差不多。看下面的示例:

     

    public class AuthInterceptor extends MethodFilterInterceptor{
        
    protected String doIntercept(ActionInvocation invocation) throws Exception {        
            Map session 
    = invocation.getInvocationContext().getSession();
            
    //如果session中存在username字段,且傳入Action實(shí)現(xiàn)了Authenticatable接口,且驗(yàn)證成功
            
    //當(dāng)然這里只是舉例子,具體要根據(jù)業(yè)務(wù)邏輯來(lái)寫(xiě)
            if(session.containsKey("username")&& (invocation instanceof Authenticatable)
                   
    && ((Authenticatable)invocation).validate((String)session.get("username"),(String)session.get("password"))){
                
    //將數(shù)據(jù)流轉(zhuǎn)給真正的Action
                return invocation.invoke();
            }
    else{
                
    //返回一個(gè)全局登錄失敗的result
                return Action.LOGIN;
            }

        }

    }

    其中,if()邏輯內(nèi)執(zhí)行了從session中取用戶信息及驗(yàn)證的邏輯,如果成功,則調(diào)用invocation.invoke()將邏輯交給Action,否則退出并返回一個(gè)全局的Login結(jié)果。


    2.聲明攔截器
    攔截器需要在struts.xml中聲明。在說(shuō)明步驟之前,先介紹一下struts中攔截器的框架。

    在struts中攔截器實(shí)際上分為攔截器和攔截器棧,攔截器棧可以包含一到多個(gè)攔截器或者攔截器棧。從上層看來(lái),攔截器和攔截器棧實(shí)際上沒(méi)有什么區(qū)別(就像操作系統(tǒng)中的文件夾和文件)。struts在入口處遞歸的調(diào)用了<default-interceptor-ref>中定義的攔截器(棧)中的所有攔截器。

    其實(shí)之前如果看過(guò)struts-default.xml的話,可以看到struts中內(nèi)建了許多的攔截器,事實(shí)上,即便我們?cè)?em>struts.xml中什么都不聲明,程序也會(huì)在后臺(tái)執(zhí)行缺省攔截器棧中定義的許多攔截器邏輯,比如說(shuō)將頁(yè)面上的field映射到對(duì)應(yīng)Action的同名屬性中、自動(dòng)執(zhí)行類(lèi)型轉(zhuǎn)換、自動(dòng)關(guān)聯(lián)驗(yàn)證xml等等。這些攔截器會(huì)在每個(gè)沒(méi)有顯式聲明攔截器的Action執(zhí)行前后被執(zhí)行。

    需要注意的是,正如上面一句所提到的,如果在Action中顯式聲明了一個(gè)攔截器,那么系統(tǒng)默認(rèn)的攔截器將不會(huì)被調(diào)用。因此,如果直接將自定義的攔截器放入Action中的話,內(nèi)建的那些攔截器將會(huì)被忽略,這會(huì)導(dǎo)致錯(cuò)誤。所以我們需要在struts.xml<package>元素下覆蓋缺省攔截器。像下面這樣:

     

    <interceptors>
                
    <interceptor-stack name="default-with-my-inteceptor">
                    
    <interceptor-ref name="defaultStack"/>
                    
    <interceptor-ref name="XXX-interceptor"/>
                
    </interceptor-stack>
                
    <interceptor name="XXX-interceptor" class="com.dev.interceptors.XXXInterceptor" />
    </interceptors>

    <default-interceptor-ref name="default-with-my-inteceptor"/>

     

    這樣就將自定義攔截器加上了struts缺省攔截器形成新的缺省攔截器。

    因?yàn)槿侄x了攔截器,雖然攔截器在通過(guò)攔截的情況下會(huì)返回特定Action的result,但有時(shí)候比如權(quán)限驗(yàn)證失敗等情況下,自定義攔截器會(huì)返回自定義的結(jié)果,不屬于任何特定Action,所以我們也需要定義一個(gè)全局result用以響應(yīng)這個(gè)攔截器的返回值。
    緊挨在<default-interceptor-ref>元素下面添加

    <global-results>
        
    <result name="" type="redirectAction">global_error.jsp</result>
    </global-results>


    注意到其result type為redirectAction重定向Action,這樣struts將以重定向方式處理該Action,并跳轉(zhuǎn)到global_error.jsp而不會(huì)顯示出最后一次執(zhí)行的Action名字。順便,Action的result缺省是以dispatcher也就是請(qǐng)求轉(zhuǎn)發(fā)的方式處理的。

    同時(shí),按照業(yè)務(wù)邏輯,有些特定Action是不能執(zhí)行自定義攔截器的。比如說(shuō),如果我們定義了一個(gè)全局的攔截器,它從session中取出用戶名和密碼進(jìn)行驗(yàn)證,驗(yàn)證通過(guò)則繼續(xù),不通過(guò)則返回到login.jsp頁(yè)面,那么很顯然login.jsp頁(yè)面提交的那個(gè)Action本身是不能使用該攔截器的,否則就沒(méi)有地方可以將用戶信息放入session了。
    這種情況下,就要借助之前提到的“特定Action中定義的攔截器會(huì)覆蓋全局設(shè)置”這個(gè)特性了。在需要屏蔽該攔截器的個(gè)別Action中顯式的聲明defaultStack攔截器(也就是struts內(nèi)建的攔截器棧),這樣,自定義攔截器在這個(gè)Action中就不會(huì)生效了。


    小結(jié)一下:
    寫(xiě)了這么多,其實(shí)大部分都在講原理,如果理解了原理,這幾部做起來(lái)是否常容易的。所以重要的是掌握原理。
    回憶一下,真正要做的只有三個(gè)地方:
    (1)寫(xiě)一個(gè)攔截器類(lèi)(實(shí)現(xiàn)接口也好,繼承抽象類(lèi)也好)
    (2)修改struts.xml聲明新的缺省攔截器棧和全局result
    (3)對(duì)于特定Action,顯式聲明defaultStack攔截器以屏蔽自定義攔截器

    另外談一點(diǎn)自己的看法:
    攔截器可以說(shuō)是struts當(dāng)之無(wú)愧的核心,無(wú)論是struts的實(shí)現(xiàn)原理還是我們基于struts搭建的應(yīng)用擴(kuò)展,攔截器都發(fā)揮了重要的作用。當(dāng)然也有可能是我自己的理解不夠深入,但是有一點(diǎn)沒(méi)想明白,就是攔截器只能基于Action發(fā)揮效用,如果一些功能和Action無(wú)關(guān),那么攔截器沒(méi)法發(fā)生效用。不知道struts底層實(shí)現(xiàn)細(xì)節(jié)中是否只開(kāi)放了基于Action的攔截器,其實(shí)理論上來(lái)說(shuō),在web.xml中設(shè)置了struts作為filter,并攔截所有請(qǐng)求,攔截器在從頁(yè)面發(fā)送至服務(wù)器被struts filter到的那一刻起(準(zhǔn)確地說(shuō)是“前一刻起”),攔截器就能發(fā)揮作用了。比如說(shuō)現(xiàn)在這種過(guò)濾器只能在頁(yè)面提交到Action時(shí)起作用,但無(wú)法防止用戶直接訪問(wèn)JSP。

    posted on 2009-02-06 14:42 bacon 閱讀(4087) 評(píng)論(1)  編輯  收藏 所屬分類(lèi): J2EE

    評(píng)論

    # re: Struts2的攔截器 2010-07-22 17:56 masuz

    在struts.xml中修改一下action擴(kuò)展名的配置,應(yīng)該就能使攔截器處理 .jsp的請(qǐng)求了:
    <constant name="struts.action.extension" value="action,jsp" />

    就是把 .jsp 請(qǐng)求也當(dāng)作action攔截下來(lái)進(jìn)行處理
      回復(fù)  更多評(píng)論   

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(1)

    隨筆分類(lèi)

    隨筆檔案

    文章分類(lèi)

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 好紧我太爽了视频免费国产| 搡女人免费视频大全| 亚洲国产人成在线观看69网站| 亚洲一区二区中文| 免费下载成人电影| 成人久久久观看免费毛片| 亚洲国产精品自在在线观看| 麻豆精品国产免费观看| 波霸在线精品视频免费观看| 亚洲天堂电影在线观看| 亚洲免费无码在线| 成人免费视频69| 国产伦精品一区二区免费| 亚洲精品中文字幕无乱码| 亚洲日本韩国在线| 国产免费不卡视频| 国产免费播放一区二区| 亚洲日本va在线观看| 精品亚洲永久免费精品| 免费涩涩在线视频网| 无码日韩精品一区二区免费暖暖| 麻豆亚洲AV成人无码久久精品 | 亚洲狠狠婷婷综合久久| 久久亚洲精品成人777大小说| 免费看美女让人桶尿口| 欧洲人免费视频网站在线| 国产亚洲福利精品一区二区| 亚洲国产成人手机在线电影bd| 亚洲日韩在线观看免费视频| 成人免费无码视频在线网站| 日韩精品免费在线视频| 成年大片免费高清在线看黄| 精品亚洲456在线播放| 久久丫精品国产亚洲av不卡| 国产亚洲精品无码专区| 国产极品美女高潮抽搐免费网站| 国产精品免费精品自在线观看| 一个人看的www免费视频在线观看| 狼色精品人妻在线视频免费| 亚洲AV无码无限在线观看不卡| 亚洲最新视频在线观看|