午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

struts2 攔截器和actioninvocation

 Y赫爾 2015-11-25

 Interceptor說明

Interceptor的接口定義沒有什么特別的地方,除了init和destory方法以外,intercept方法是實(shí)現(xiàn)整個(gè)攔截器機(jī)制的核心方法。而它所依賴的參數(shù)ActionInvocation則是我們之前章節(jié)中曾經(jīng)提到過的著名的Action調(diào)度者。

我在這里需要指出的是一個(gè)很重要的方法invocation.invoke()。這是ActionInvocation中的方法,而ActionInvocation是Action調(diào)度者,所以這個(gè)方法具備以下2層含義(詳細(xì)看DefaultActionInvocation源代碼): 
1. 如果攔截器堆棧中還有其他的Interceptor,那么invocation.invoke()將調(diào)用堆棧中下一個(gè)Interceptor的執(zhí)行。 

2. 如果攔截器堆棧中只有Action了,那么invocation.invoke()將調(diào)用Action執(zhí)行。

 

3.

DefaultActionInvocation部分源代碼:

      if (interceptors.hasNext()) {
       final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
       UtilTimerStack.profile('interceptor: '+interceptor.getName(), 
         new UtilTimerStack.ProfilingBlock<String>() {
       public String doProfiling() throws Exception {
           resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);//遞歸調(diào)用攔截器
           return null;
       }
       });
      } else {
       resultCode = invokeActionOnly();
      }

每個(gè)攔截器中的代碼的執(zhí)行順序,在Action之前,攔截器的執(zhí)行順序與堆棧中定義的一致;而在Action和Result之后,攔截器的執(zhí)行順序與堆棧中定義的順序相反。

Interceptor攔截類型 

從上面的分析,我們知道,整個(gè)攔截器的核心部分是invocation.invoke()這個(gè)函數(shù)的調(diào)用位置。事實(shí)上,我們也正式根據(jù)這句代碼的調(diào)用位置,來進(jìn)行攔截類型的區(qū)分的。在Struts2中,Interceptor的攔截類型,分成以下三類: 

1. before 

before攔截,是指在攔截器中定義的代碼,它們存在于invocation.invoke()代碼執(zhí)行之前。這些代碼,將依照攔截器定義的順序,順序執(zhí)行。 

2. after 

after攔截,是指在攔截器中定義的代碼,它們存在于invocation.invoke()代碼執(zhí)行之后。這些代碼,將一招攔截器定義的順序,逆序執(zhí)行。

 

PreResultListener 
有的時(shí)候,before攔截和after攔截對我們來說是不夠的,因?yàn)槲覀冃枰贏ction執(zhí)行完之后,但是還沒有回到視圖層之前,做一些事情。Struts2同樣支持這樣的攔截,這種攔截方式,是通過在攔截器中注冊一個(gè)PreResultListener的接口來實(shí)現(xiàn)的。

如:在攔截器中使用如下代碼,其中MyPreResultListener實(shí)現(xiàn)了PreResultListener 接口并在beforeResult方法中做了一些事情然后在攔截器類中加入action.addPreResultListener(new MyPreResultListener());

 

從源碼中,我們可以看到,我們之前提到的Struts2的Action層的4個(gè)不同的層次,在這個(gè)方法中都有體現(xiàn),他們分別是:攔截器(Interceptor)、Action、PreResultListener和Result。在這個(gè)方法中,保證了這些層次的有序調(diào)用和執(zhí)行

 

問題

使用Struts2作為web框架,知道它的攔截器(Interceptor)機(jī)制,類似與Filter和Spring的AOP,于是實(shí)現(xiàn)了一個(gè)為Action增加自定義前置(before)動作和后置動作(after)的攔截器(曰:WInterceptor),不過用一段時(shí)間發(fā)現(xiàn),在WInterceptor的after中,對Action對象的屬性修改在頁面看不到,對請求對象的屬性設(shè)置也無效。為什么在調(diào)用了Action之后(invokeAction())之后,request就不能使用了呢,攔截器不能改變Action的Result么?

 問題的關(guān)鍵在于,在調(diào)用actionInvocation.invoke()的之后,不僅執(zhí)行類Action,也執(zhí)行類Result。因而,等退回到攔截器的調(diào)用代碼時(shí),Result已經(jīng)生成,View已經(jīng)確定,這時(shí)你再修改模型(Action的屬性)或請求對象的屬性,對視圖不會有任何影響。

解決辦法:

 

 方法一:使用現(xiàn)成的PreResultListener監(jiān)聽器事件

搞清楚原因,卷起袖子干吧,只要讓W(xué)Interpretor的after事件,放在Result的生成之前就行了。

看看XWork的攔截器接口注入的actionInvocation,其實(shí)就提供增加Result執(zhí)行的前置監(jiān)聽事件-PreResultListener:

Java代碼 復(fù)制代碼 收藏代碼
  1.   
  2. void addPreResultListener(PreResultListener listener);  
void addPreResultListener(PreResultListener listener);

 

因此,讓攔截器實(shí)現(xiàn)這個(gè)接口,就可以自然實(shí)現(xiàn)Action執(zhí)行after事件了。

 

 

方法二,實(shí)現(xiàn)自己的 ActionInvocation ,手動分離Action和Result的執(zhí)行

本來前面的方法已經(jīng)很好了,可是,可是啊,在addPreResultListener里的異常,不會被Struts的框架捕獲,而且,addPreResultListener接口不能傳遞自己的上下文參數(shù),難道動用ThreadLocal傳參?

 

研究了一下XWork的ActionInvocation 接口默認(rèn)實(shí)現(xiàn)類DefaultActionInvocation, 寫了一個(gè)包裝類,將Action的執(zhí)行和Result的生成完全分開,或許有人用的著,放上來,見附件(ActionInvocationWrapper),如有不妥之處請告知。

 

exeucteAction是執(zhí)行Action,executeResult是執(zhí)行Result

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多