5、Interceptors
Interceptors允許在調(diào)用堆棧中包含任意在Action處理之前和/或處理之后執(zhí)行的代碼。這是你的代碼簡單,更能重用。Xwork和WebWork的大部分特性都是Interceptors實現(xiàn)的。你可以通過外部配置,按照你定義的順序,對指定的Action應(yīng)用你自己的Interceptors。
當(dāng)你訪問.action URL時,WebWork的ServletDispatcher啟動Action對象,在Action被執(zhí)行之前,啟動允許被其它的對象中斷,這就稱Interceptor。在指定的Action之前(或之后)執(zhí)行Interceptor,只要在xwork.xml中配置屬性。下面是4.1.1節(jié)中展示UI標(biāo)記用法的例子的Interceptor配置:
<action name="formProcessing" class="lesson04_01_01.FormProcessingAction">
<result name="input" type="dispatcher">ex01-index.jsp</result>
<result name="success" type="dispatcher">ex01-success.jsp</result>
<interceptor-ref name="validationWorkflowStack" />
</action>
FormProcessingAction使用了validationWorkflowStack。這是一個Interceptor堆,組織一組按順序執(zhí)行的Interceptors。ValidationWorkflowStack在webwork-default.xml中配置,所以我們只要使用<interceptor-ref />在Action配置中,或使用<default-interceptor-ref />在package配置中使用它。下面是HelloWebWorld例子的Interceptor配置:
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">
<xwork>
<!-- Include webwork defaults (from WebWork-2.1 JAR). -->
<include file="webwork-default.xml" />
<!-- Configuration for the default package. -->
<package name="default" extends="webwork-default">
<!-- Default interceptor stack. -->
<default-interceptor-ref name="defaultStack" />
<!-- Action: Lesson 03: HelloWebWorldAction. -->
<action name="helloWebWorld" class="lesson03.HelloWebWorldAction">
<result name="success" type="dispatcher">ex01-success.jsp</result>
</action>
</package>
</xwork>
看一下Interceptor如何工作的
l 創(chuàng)建Interceptor類,需要擴展com.opensymphony.xwork.interceptor.Interceptor接口(包含在xwork-1.0.jar);
l 在xwork.xml文件中,使用<interceptors />內(nèi)嵌的<interceptor />聲明Interceptor類;
l 使用<interceptor-stack />創(chuàng)建Interceptor堆(可選);
l 使用<interceptor-ref /> 或<default-interceptor-ref />哪些Interceptor由哪個Action使用;前者由指定Action使用,后者為所有Action使用
(1)webwork-default.xml
讓我們看一下webwork-default.xml的內(nèi)容:
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">
<xwork>
<package name="webwork-default">
<result-types>
<result-type name="dispatcher" default="true"
class="com.opensymphony.webwork.dispatcher.ServletDispatcherResult"/>
<result-type name="redirect"
class="com.opensymphony.webwork.dispatcher.ServletRedirectResult"/>
<result-type name="velocity"
class="com.opensymphony.webwork.dispatcher.VelocityResult"/>
<result-type name="chain"
class="com.opensymphony.xwork.ActionChainResult"/>
<result-type name="xslt"
class="com.opensymphony.webwork.views.xslt.XSLTResult"/>
</result-types>
<interceptors>
<interceptor name="timer"
class="com.opensymphony.xwork.interceptor.TimerInterceptor"/>
<interceptor name="logger"
class="com.opensymphony.xwork.interceptor.LoggingInterceptor"/>
<interceptor name="chain"
class="com.opensymphony.xwork.interceptor.ChainingInterceptor"/>
<interceptor name="static-params"
class="com.opensymphony.xwork.interceptor.StaticParametersInterceptor"/>
<interceptor name="params"
class="com.opensymphony.xwork.interceptor.ParametersInterceptor"/>
<interceptor name="model-driven"
class="com.opensymphony.xwork.interceptor.ModelDrivenInterceptor"/>
<interceptor name="component"
class="com.opensymphony.xwork.interceptor.component.ComponentInterceptor"/>
<interceptor name="token"
class="com.opensymphony.webwork.interceptor.TokenInterceptor"/>
<interceptor name="token-session"
class="com.opensymphony.webwork.interceptor.TokenSessionStoreInterceptor"/>
<interceptor name="validation"
class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
<interceptor name="workflow"
class="com.opensymphony.xwork.interceptor.DefaultWorkflowInterceptor"/>
<interceptor name="servlet-config"
class="com.opensymphony.webwork.interceptor.ServletConfigInterceptor"/>
<interceptor name="prepare"
class="com.opensymphony.xwork.interceptor.PrepareInterceptor"/>
<interceptor name="conversionError"
class="com.opensymphony.webwork.interceptor.WebWorkConversionErrorInterceptor"/>
<interceptor-stack name="defaultStack">
<interceptor-ref name="static-params"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
</interceptor-stack>
<interceptor-stack name="validationWorkflowStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
</interceptors>
</package>
</xwork>
既然在我們的xwork.xml中包含了webwork-default.xml,我們就可以在Action中使用這些Interceptor或Interceptor堆。下面是這些Interceptor做的事情:
l timer:對Action的執(zhí)行進(jìn)行計時(包括嵌套的Interceptor和視圖)
l chain:使前一個Action的屬性對當(dāng)前的Action有效,通常創(chuàng)建Action鏈
l static-params:設(shè)置xwork.xml中的參數(shù)到Action中(<action />內(nèi)嵌的<param />)
l params:設(shè)置請求參數(shù)(POST或GET)到Action中
l model-driven:如果Action實現(xiàn)ModelDriven,將getModel()的結(jié)果推到Value Stack中
l component:使能和注冊組件,使其對Action有效
l token:檢查Action中的有效token,防止重復(fù)提交
l token-session:同上,但是當(dāng)處理到無效token時,在session中保存提交的數(shù)據(jù)
l validation:使用在{Action}-vaildation.xml中定義的驗證器進(jìn)行數(shù)據(jù)驗證
l workflow:調(diào)用Action類中的validate()方法,在發(fā)生錯誤時,返回INPUT視圖;應(yīng)該和validation Interceptor一起使用
l servlet-config:獲得對HttpServletRequest和HttpServletResponse的訪問(由于綁定到Servlet API,最好不要使用)
l prepare
l conversionError
(2)創(chuàng)建自己的Interceptor
如果上面的Interceptor沒有適合你的,你可以創(chuàng)建自己的Interceptor。下面的例子假設(shè)我們需要一個Interceptor在session中根據(jù)當(dāng)天時間放置一個歡迎信息:
GreetingInterceptor.java:
package lesson05;
import java.util.Calendar;
import com.opensymphony.xwork.interceptor.Interceptor;
import com.opensymphony.xwork.ActionInvocation;
public class GreetingInterceptor implements Interceptor {
public void init() { }
public void destroy() { }
public String intercept(ActionInvocation invocation) throws Exception {
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
String greeting = (hour < 6) ? "Good evening" :
((hour < 12) ? "Good morning":
((hour < 18) ? "Good afternoon": "Good evening"));
invocation.getInvocationContext().getSession().put("greeting", greeting);
String result = invocation.invoke();
return result;
}
}
xwork.xml:
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">
<xwork>
<!-- Include webwork defaults (from WebWork-2.1 JAR). -->
<include file="webwork-default.xml" />
<!-- Configuration for the default package. -->
<package name="default" extends="webwork-default">
<interceptors>
<interceptor name="greeting" class="section02.lesson05.GreetingInterceptor" />
</interceptors>
<!-- Action: Lesson 5: GreetingInterceptor. -->
<action name="greetingAction" class="lesson05.GreetingAction">
<result name="success" type="velocity">ex01-result.vm</result>
<interceptor-ref name="greeting" />
</action>
</package>
</xwork>
GreetingAction.java:
package lesson05;
import com.opensymphony.xwork.ActionSupport;
public class GreetingAction extends ActionSupport {
public String execute() throws Exception {
return SUCCESS;
}
}
ex01-result.vm:
<html>
<head>
<title>WebWork Tutorial - Lesson 5 - Example 1</title>
</head>
<body>
#set ($ses = $req.getSession())
<p><b>${ses.getAttribute('greeting')}!</b></p>
</body>
</html>
Interceptor類要擴展com.opensymphony.xwork.interceptor.Interceptor接口:init()在Interceptor初始化時調(diào)用;destroy()在銷毀時調(diào)用;intercept(ActionInvocation invocation)是處理的中心。
invocation.invoke()用來調(diào)用Interceptor堆中下一個Interceptor,或是Action(如果沒有的話)。因此,我們完全可以繞開Action而返回結(jié)果(不執(zhí)行Action)。
上面的例子是在Action執(zhí)行之前調(diào)用,如果要在Action執(zhí)行之后調(diào)用Interceptor,只要將執(zhí)行代碼放在invocation.invoke()之后。
WebWork提供一個實現(xiàn)這種方式的抽象類com.opensymphony.xwork.interceptor.AroundInterceptor,你只要實現(xiàn)它的before(ActionInvocation invocation)和 after(ActionInvocation dispatcher, String result)方法就可以了。