WebWork項目建立在XWork項目上。入口Servlet是WebWork項目中定義的ServletDispatcher,而Action在XWork項目中定義。
XWork Action接口的execute()方法沒有參數,不像Struts Action那樣接受request, response參數,所以XWork Action能夠脫離Web環境被直接調用,便于單元測試。
這里引入了一個問題。沒有了request參數,那么XWork Action如何獲得request parameters作為輸入數據?又通過什么橋梁(Struts用request.setAttribute)把結果數據傳送到View層?
在Web Work中,只能通過Action本身的getter, setter屬性來傳送輸入參數和輸出結果。
比如,我們有這樣一個實現了XWork Action接口的類,
YourAction implements Action{
int productId = null;
String productName = null;
public void setProductId(int productId){this.productId = productId;}
public String getProductName(){return productName;}
public String execute(){
productName = findNameById(productId);
return “success”;
}
}
這個類里面的productId將接受request輸入參數,productName是輸出到頁面顯示的結果。
比如,這樣的請求,http://yourhost/yourapp/MyAction.action?productId=1
Web Work會把1填到YourAction的productId里面,然后執行execute()方法,JSP里的語句<ww:property value=“productName”>會把YourAction的productName顯示在頁面上。
如果一個Web Framework采用了這種屏蔽Action的request, response參數的設計方式,一般也同時會采用這種Action和輸入輸出數據結合成一體的解決方式。類似的情形也存在于Tapestry和Maverick中,后面會講到。
當WebWork ServletDispatcher接收到HTTP Request的時候,首先把所有相關的信息(包括request, response, session, servlet config, servelt context, 所有request參數)等存放到AcationContext中,然后根據Interceptor配置信息,生成一個YourAction的動態代理類對象。實際上運行的正是這個代理對象,如同Servlet Filter的工作機制一般,所有注入的Interceptor方法會先于Actio方法運行。
我們來看一下Action和Interceptor的地位:Action沒有參數,無法獲得ActionContext;而Interceptor接受的ActionInvoication參數擁有包括ActionContext在內的所有重要信息。
這種權力分配的不平等,注定了Action的作用非常有限,只限于調用商業邏輯,然后返回一個成功與否標志。所有與外部Web世界打交道、協調內部工作流程的重擔,都責無旁貸地落在Interceptor的肩上。
我們可以設想一個極端的例子。我們聲明一批不做任何事情的空Action,我們只是需要它們的空殼類名;我們制作一批對應的Interceptor,所有的轉發控制、商業邏輯都在Interceptor上實現,然后把Interceptor都注入到對應的空Action。這在理論上是完全可行的。
在Web海洋的包圍中,Action可少,Interceptor不可少。Action是一個孤島,如果沒有外來盟友Interceptor的協助,只能在自己的小范圍內獨立作戰(比如Unit Test),而對整體大局的作戰目標無法產生影響。
下面我們來看一下Action是如何在Interceptor的全程監管下工作的。
在WebWork中,我們需要如下配置XWork.xml。
<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: YourAction. -->
<action name="youraction" class="yourapp.YourAction">
<result name="success" type="dispatcher">
YourAction.jsp
</result>
</action>
</package>
</xwork>
webwork-default.xml里面的相關定義如下:
<interceptors>
<interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
<interceptor name="static-params" class="com.opensymphony.xwork.interceptor.
StaticParametersInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork.interceptor.ParametersInterceptor "/>
<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>
</interceptors>
從上述的配置信息中可以看出,YourAction執行execute()方法的前后,會被
defaultStack所定義的三個Intercepter截獲。這些Interceptor的任務之一就是把輸入參數設置到Action的對應屬性當中。
如果我們需要加入對YourAction的屬性的驗證功能,只要把上述定義中的validation Interceptor加入到defaultStack中就可以了。當然,實際工作還沒有這么簡單,一般來說,還要為每個進行屬性驗證的Action的都配置一份validation.xml。
XWork Interceptor能夠在Package和Action級別上,進行截獲處理。
Servlet Filter能夠在URL Patten級別上,進行截獲處理。雖然實際上,Servlet Filter截獲的是Servlet,但某些情況下,可以達到和截獲一批Action的同樣效果。
比如,在Web Work中,我們可以為所有admin package的Action,加入一個Interceptor,當檢查到當前Session的用戶沒有admin權限時,統一返回一個警告頁面:您沒有足夠的權限執行這個操作。
我們看到也可以為所有URL Pattern為“admin/*.action”的URL定義一個Servlet Filter,當檢查到當前Session的用戶沒有admin權限時,統一返回一個警告頁面:您沒有足夠的權限執行這個操作。
WebWork的Interceptor配置是相當靈活的,相當于對Action實現了AOP。Interceptor相當于Aspect,基類AroundInterceptor的before(), after()方法相當于Advice。
另外,XWork也提供了從XML配置文件裝配Component的機制,相當于實現了對于Component的IoC。
(申明:本文來源于網絡,摘錄于此,僅為日后方便查看)