| Struts2攔截器 一、定義理解 1. Struts2攔截器是在訪問(wèn)某個(gè)Action或Action的某個(gè)方法,字段之前或之后實(shí)施攔截,并且Struts2攔截器是可插拔的,攔截器是AOP的一種實(shí)現(xiàn). 2. 攔截器棧(Interceptor Stack)。Struts2攔截器棧就是將攔截器按一定的順序聯(lián)結(jié)成一條鏈。在訪問(wèn)被攔截的方法或字段時(shí),Struts2攔截器鏈中的攔截器就會(huì)按其之前定義的順序被調(diào)用。 二、實(shí)現(xiàn)(Struts2攔截器原理) Struts2攔截器的實(shí)現(xiàn)原理相對(duì)簡(jiǎn)單,當(dāng)請(qǐng)求到達(dá)Struts 2的ServletDispatcher時(shí),Struts 2會(huì)查找配置文件,并根據(jù)其配置實(shí)例化相對(duì)的攔截器對(duì)象,然后串成一個(gè)列表(list),最后一個(gè)一個(gè)地調(diào)用列表中的攔截器。 
當(dāng)Action請(qǐng)求到來(lái)的時(shí)候,會(huì)由系統(tǒng)的代理生成一個(gè)Action的代理對(duì)象,由這個(gè)代理對(duì)象調(diào)用Action的execute()或指定的方法,并在struts.xml中查找與該Action對(duì)應(yīng)的攔截器。如果有對(duì)應(yīng)的攔截器,就在Action的方法執(zhí)行前(后)調(diào)用這些攔截器;如果沒(méi)有對(duì)應(yīng)的攔截器則執(zhí)行Action的方法。其中系統(tǒng)對(duì)于攔截器的調(diào)用,是通過(guò)ActionInvocation來(lái)實(shí)現(xiàn)的 三、深入Struts2攔截器 Struts2規(guī)定用戶自定義攔截器必須實(shí)現(xiàn)com.opensymphony.xwork2.interceptor.Interceptor接口。該接口聲明了3個(gè)方法, 
 其中,init和destroy方法會(huì)在程序開(kāi)始和結(jié)束時(shí)各執(zhí)行一遍,不管使用了該攔截器與否,只要在struts.xml中聲明了該Struts2攔截器就會(huì)被執(zhí)行。另外,Interceptor的接口定義沒(méi)有什么特別的地方,除了init和destory方法以外,intercept方法是實(shí)現(xiàn)整個(gè)攔截器機(jī)制的核心方法。而它所依賴的參數(shù)ActionInvocation則是著名的Action調(diào)度者。 
 不過(guò),struts中又提供了幾個(gè)抽象類,不必單一方式去實(shí)現(xiàn)接口來(lái)定義攔截器,但其實(shí)質(zhì)還是實(shí)現(xiàn)Interceptor接口 
 
 其中AbstractInterceptor提供了init()和destroy()的空實(shí)現(xiàn),使用時(shí)只需要覆蓋intercept()方法; 重點(diǎn):在ActionInvocation中,一個(gè)很重要的方法invocation.invoke(),invocation.invoke()這個(gè)方法其實(shí)是整個(gè)攔截器框架的實(shí)現(xiàn)核心;其實(shí)在invocation.invoke()中調(diào)用intercept()的方法中又對(duì)ActionInvocation的invoke()方法進(jìn)行遞歸調(diào)用,ActionInvocation循環(huán)嵌套在intercept()中,一直到語(yǔ)句result = invocation.invoke()執(zhí)行結(jié)束。這樣,Interceptor又會(huì)按照剛開(kāi)始執(zhí)行的逆向順序依次執(zhí)行結(jié)束。一個(gè)有序鏈表,通過(guò)遞歸調(diào)用,變成了一個(gè)堆棧執(zhí)行過(guò)程,將一段有序執(zhí)行的代碼變成了2段執(zhí)行順序完全相反的代碼過(guò)程,從而巧妙地實(shí)現(xiàn)了AOP。這也就成為了Struts2的Action層的AOP基礎(chǔ)。 其中,invocation.invoke()這個(gè)方法具有以下兩層含義: 
 1. 如果攔截器堆棧中還有其他的Interceptor,那么invocation.invoke()將調(diào)用堆棧中下一個(gè)Interceptor的執(zhí)行。 基于此,我們可以得出結(jié)論: 
 1. 如果在攔截器中,我們不使用invocation.invoke()來(lái)完成堆棧中下一個(gè)元素的調(diào)用,而是直接返回一個(gè)字符串作為執(zhí)行結(jié)果,那么整個(gè)執(zhí)行將被中止。 最后,我們分析一下攔截器和過(guò)濾器的區(qū)別: 
  (1)攔截器是基于JAVA反射機(jī)制的,而過(guò)濾器是基于函數(shù)回調(diào)的。 | 
|  | 
來(lái)自: liang1234_ > 《web開(kāi)發(fā)》