java 拦截器ajax_(转)拦截器深入实践 - JAVA XML JAVASCRIPT AJAX CSS - BlogJava
Interceptor的定義
我們來看一下Interceptor的接口的定義:
Java代碼
publicinterfaceInterceptorextendsSerializable?{
/**
*?Called?to?let?an?interceptor?clean?up?any?resources?it?has?allocated.
*/
voiddestroy();
/**
*?Called?after?an?interceptor?is?created,?but?before?any?requests?are?processed?using
*?{@link?#intercept(com.opensymphony.xwork2.ActionInvocation)?intercept}?,?giving
*?the?Interceptor?a?chance?to?initialize?any?needed?resources.
*/
voidinit();
/**
*?Allows?the?Interceptor?to?do?some?processing?on?the?request?before?and/or?after?the?rest?of?the?processing?of?the
*?request?by?the?{@link?ActionInvocation}?or?to?short-circuit?the?processing?and?just?return?a?String?return?code.
*
*?@return?the?return?code,?either?returned?from?{@link?ActionInvocation#invoke()},?or?from?the?interceptor?itself.
*?@throws?Exception?any?system-level?error,?as?defined?in?{@link?com.opensymphony.xwork2.Action#execute()}.
*/
String?intercept(ActionInvocation?invocation)throwsException;
}
public interface Interceptor extends Serializable {
/**
* Called to let an interceptor clean up any resources it has allocated.
*/
void destroy();
/**
* Called after an interceptor is created, but before any requests are processed using
* {@link #intercept(com.opensymphony.xwork2.ActionInvocation) intercept} , giving
* the Interceptor a chance to initialize any needed resources.
*/
void init();
/**
* Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the
* request by the {@link ActionInvocation} or to short-circuit the processing and just return a String return code.
*
* @return the return code, either returned from {@link ActionInvocation#invoke()}, or from the interceptor itself.
* @throws Exception any system-level error, as defined in {@link com.opensymphony.xwork2.Action#execute()}.
*/
String intercept(ActionInvocation invocation) throws Exception;
}
Interceptor的接口定義沒有什么特別的地方,除了init和destory方法以外,intercept方法是實(shí)現(xiàn)整個(gè)攔截器機(jī)制的核心方法。而它所依賴的參數(shù)ActionInvocation則是我們之前章節(jié)中曾經(jīng)提到過的著名的Action調(diào)度者。
我們?cè)賮砜纯匆粋€(gè)典型的Interceptor的抽象實(shí)現(xiàn)類:
Java代碼
publicabstractclassAroundInterceptorextendsAbstractInterceptor?{
/*?(non-Javadoc)
*?@see?com.opensymphony.xwork2.interceptor.AbstractInterceptor#intercept(com.opensymphony.xwork2.ActionInvocation)
*/
@Override
publicString?intercept(ActionInvocation?invocation)throwsException?{
String?result?=null;
before(invocation);
//?調(diào)用下一個(gè)攔截器,如果攔截器不存在,則執(zhí)行Action
result?=?invocation.invoke();
after(invocation,?result);
returnresult;
}
publicabstractvoidbefore(ActionInvocation?invocation)throwsException;
publicabstractvoidafter(ActionInvocation?invocation,?String?resultCode)throwsException;
}
public abstract class AroundInterceptor extends AbstractInterceptor {
/* (non-Javadoc)
* @see com.opensymphony.xwork2.interceptor.AbstractInterceptor#intercept(com.opensymphony.xwork2.ActionInvocation)
*/
@Override
public String intercept(ActionInvocation invocation) throws Exception {
String result = null;
before(invocation);
// 調(diào)用下一個(gè)攔截器,如果攔截器不存在,則執(zhí)行Action
result = invocation.invoke();
after(invocation, result);
return result;
}
public abstract void before(ActionInvocation invocation) throws Exception;
public abstract void after(ActionInvocation invocation, String resultCode) throws Exception;
}
在這個(gè)實(shí)現(xiàn)類中,實(shí)際上已經(jīng)實(shí)現(xiàn)了最簡單的攔截器的雛形。或許大家對(duì)這樣的代碼還比較陌生,這沒有關(guān)系。我在這里需要指出的是一個(gè)很重要的方法invocation.invoke()。這是ActionInvocation中的方法,而ActionInvocation是Action調(diào)度者,所以這個(gè)方法具備以下2層含義:
1. 如果攔截器堆棧中還有其他的Interceptor,那么invocation.invoke()將調(diào)用堆棧中下一個(gè)Interceptor的執(zhí)行。
2. 如果攔截器堆棧中只有Action了,那么invocation.invoke()將調(diào)用Action執(zhí)行。
所以,我們可以發(fā)現(xiàn),invocation.invoke()這個(gè)方法其實(shí)是整個(gè)攔截器框架的實(shí)現(xiàn)核心?;谶@樣的實(shí)現(xiàn)機(jī)制,我們還可以得到下面2個(gè)非常重要的推論:
1. 如果在攔截器中,我們不使用invocation.invoke()來完成堆棧中下一個(gè)元素的調(diào)用,而是直接返回一個(gè)字符串作為執(zhí)行結(jié)果,那么整個(gè)執(zhí)行將被中止。
2. 我們可以以invocation.invoke()為界,將攔截器中的代碼分成2個(gè)部分,在invocation.invoke()之前的代碼,將會(huì)在Action之前被依次執(zhí)行,而在invocation.invoke()之后的代碼,將會(huì)在Action之后被逆序執(zhí)行。
由此,我們就可以通過invocation.invoke()作為Action代碼真正的攔截點(diǎn),從而實(shí)現(xiàn)AOP。
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í)行。
3. PreResultListener
有的時(shí)候,before攔截和after攔截對(duì)我們來說是不夠的,因?yàn)槲覀冃枰贏ction執(zhí)行完之后,但是還沒有回到視圖層之前,做一些事情。Struts2同樣支持這樣的攔截,這種攔截方式,是通過在攔截器中注冊(cè)一個(gè)PreResultListener的接口來實(shí)現(xiàn)的。
Java代碼
publicinterfacePreResultListener?{
/**
*?This?callback?method?will?be?called?after?the?Action?execution?and?before?the?Result?execution.
*
*?@param?invocation
*?@param?resultCode
*/
voidbeforeResult(ActionInvocation?invocation,?String?resultCode);
}
public interface PreResultListener {
/**
* This callback method will be called after the Action execution and before the Result execution.
*
* @param invocation
* @param resultCode
*/
void beforeResult(ActionInvocation invocation, String resultCode);
}
在這里,我們看到,Struts2能夠支持如此多的攔截類型,與其本身的數(shù)據(jù)結(jié)構(gòu)和整體設(shè)計(jì)有很大的關(guān)系。正如我在之前的文章中所提到的:
downpour 寫道
因?yàn)锳ction是一個(gè)普通的Java類,而不是一個(gè)Servlet類,完全脫離于Web容器,所以我們就能夠更加方便地對(duì)Control層進(jìn)行合理的層次設(shè)計(jì),從而抽象出許多公共的邏輯,并將這些邏輯脫離出Action對(duì)象本身。
我們可以看到,Struts2對(duì)于整個(gè)執(zhí)行的劃分,從Interceptor到Action一直到Result,每一層都職責(zé)明確。不僅如此,Struts2還為每一個(gè)層次之前都設(shè)立了恰如其分的插入點(diǎn)。使得整個(gè)Action層的擴(kuò)展性得到了史無前例的提升。
Interceptor執(zhí)行順序
Interceptor的執(zhí)行順序或許是我們?cè)谡麄€(gè)過程中最最關(guān)心的部分。根據(jù)上面所提到的概念,我們實(shí)際上已經(jīng)能夠大致明白了Interceptor的執(zhí)行機(jī)理。我們來看看Struts2的Reference對(duì)Interceptor執(zhí)行順序的一個(gè)形象的例子。
如果我們有一個(gè)interceptor-stack的定義如下:
Xml代碼
那么,整個(gè)執(zhí)行的順序大概像這樣:
在這里,我稍微改了一下Struts2的Reference中的執(zhí)行順序示例,使得整個(gè)執(zhí)行順序更加能夠被理解。我們可以看到,遞歸調(diào)用保證了各種各樣的攔截類型的執(zhí)行能夠井井有條。
請(qǐng)注意在這里,每個(gè)攔截器中的代碼的執(zhí)行順序,在Action之前,攔截器的執(zhí)行順序與堆棧中定義的一致;而在Action和Result之后,攔截器的執(zhí)行順序與堆棧中定義的順序相反。
總結(jié)
以上是生活随笔為你收集整理的java 拦截器ajax_(转)拦截器深入实践 - JAVA XML JAVASCRIPT AJAX CSS - BlogJava的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 主板光盘怎么安装win7系统教程 如何安
- 下一篇: asp.net button创建控件时出