雖然現在 MVC 框架層出不窮,但做為 Struts 前身的 webwork。 其經典程度不亞於貝利之於足球,雙 11 之於淘寶特賣。 本篇將結合 webwork controller 配置文件 xwork.xml 的配置項淺析。 來一起看看當年叱吒風雨的 mvc 框架是怎樣滿足變更的業務需求。 1 ...
雖然現在 MVC 框架層出不窮,但做為 Struts 前身的 webwork。
其經典程度不亞於貝利之於足球,雙 11 之於淘寶特賣。
本篇將結合 webwork controller 配置文件 xwork.xml 的配置項淺析。
來一起看看當年叱吒風雨的 mvc 框架是怎樣滿足變更的業務需求。
1. xwork.xml 主文件
xwork.xml 是 WebWork 自身的配置文件,實際開發中它是配置文件的主幹骨架。
xwork 定義了一個 default 包,通過 include 包含 xwork 子文件。如下所示:
<!DOCTYPE xwork
PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">
<xwork>
<include file="webwork-default.xml"/>
<include file="common.xml"/>
<include file="user.xml"/>
</xwork>
2. xwork.xml 子文件
xwork 子文件一方面有效地對大型程式進行分解,符合程式開發的模塊化切分。
另一方面幫助我們遍歷整個程式,有助於日後的運維。
由於 webwork 開發過程中 xwork.xml 的結構定義是一致的,保證了較低的學習成本。
<!DOCTYPE xwork
PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">
<xwork>
<package name="user" extends="webwork-default" systemId="1001" caption="用戶管理">
<default-interceptor-ref name="defaultStack" />
<action name="dirUser" class="com.rambo.app.base.user.action.DirUser" caption="查詢用戶" event-type="5">
<result name="success" type="dispatcher">
<param name="location">/user/diruser.jsp</param>
</result>
<result name="error" type="redirect">
<param name="location">doError.action</param>
</result>
</action>
<action name="addUser" class="com.rambo.app.base.user.action.AddUser" caption="添加用戶" event-type="3">
<result name="success" type="dispatcher">
<param name="location">/result.jsp</param>
</result>
<result name="error" type="dispatcher">
<param name="location">/result.jsp</param>
</result>
<interceptor-ref name="modelDrivenStack" />
</action>
</package>
</xwork>
2.1 package
包: package,包的名稱可以理解為模塊的名稱(各子文件包名稱不能重覆)。所有的 action 定義在包的下一層。
命名空間:namespace,如:namespace="/user",描述子模塊 jsp 文件的所在路徑,同時明確了請求訪問時的 url 網址:/user/*.action。
命名空間為空則請求訪問時的 url 網址:/*.action。
命名空間的好處:
1) 體現模塊化
2) 命名空間為空,則訪問請求的 url 網址均為/*.action,容易衝突
2.2 action
action name:對應請求的名稱,如 dirUser,url:/user/dirUser.action
action class:com.rambo.app.base.user.action.DirUser 後臺接收請求對應的 java 處理類
action.result.location:diruser.jsp 對處理結果進行展示,文件所在目錄位置為 /user/diruser.jsp
2.3 result
ServletDispatcher 是 WebWork 框架機制的核心。它和 Action 在 MVC 模式中,扮演著控制器的角色,MVC 模式通過控制器實現了模型和視圖的分離。
Xwork 文件中的 Result 是 Action 執行完返回的一個字元串常量,它表示Action 執行完成的狀態,比如:執行成功、執行失敗等。
WebWork 的 Action 提供了預設的幾種(包括:success、error、login、none、input 等)另外 Result 完全可以自己定義,只要是一個字元串常量就可以了。
Result 標簽定義中 name 為返回的字元串常量值,如:name="success"表示
Action 執行成功,返回結果就將根據此標簽的具體配置進行視圖輸出。
type 對應 Result Type 類,它在 Action 執行完成並返回 Result 之後,決定採用哪一種視圖技術,將執行結果展現給用戶,主要包括:
type | 參數 | 描述 |
dispatcher |
location(必須) |
調度到 jsp 頁面展現,其中 Action 請求對應 java 處理程式中的 |
redirect | location(必須) parse |
將響應重定向到瀏覽器指定的位置,它將會導致 Action 執行完成 |
chain |
actionName(必須) |
Action Chaining:一種特殊的視圖結果,將 Action 執行完之後鏈接到另一個 |
1. type = dispatcher
<result name="success" type="dispatcher">
<param name="location">userinfo.jsp</param>
</result>
簡寫:<result name="success" type="dispatcher">userinfo.jsp</result>
2. type = redirect
<result name="error" type="redirect">
<param name="location">../userinfo.jsp</param>
</result>
簡寫:<result name="error" type="redirect">../userinfo.jsp</result>
3. type = chain
<result name="success" type="chain">
<param name="actionName">rambo</param>
</result>
Action:
<action name="rambo" class="myPackage.barAction">
...
</action>
2.4 interceptor
WebWork 截獲 Action 請求,在 Action 執行之前或之後調用攔截器方法。這樣,可以用插拔的方式將功能註入 Action 中。
實際開發中最常用攔截器主要封裝了對錶單參數提交時的處理,如對象化等,包括如下三類:
1) 預設攔截器 <interceptor-ref name="defaultStack"/>
2) 支持模型驅動攔截器 <interceptor-ref name="modelStack"/>
3) 支持文件上傳攔截器 <interceptor-ref name="uploadStack"/>
2.4.1 defaultStack 預設攔截器
預設的表單處理攔截器。Xwork.xml 定義的 Action 只要繼承 ActionSupport類,通過預設攔截器就可以自動將 jsp 表單數據轉換為 java 文件定義的相應變數。
註意:jsp 文件表單 input 中的 name 名要與 java 文件中的變數名相對應。
如下麵示例中的 sysId 和 gUser 對象。
前端:
<form name="form1" id="form1" action="login.action" method="post">
<input type="hidden" name="sysId" id="sysId"/><br/>
用戶名:<input name="gUser.email" id="gUser.email"/><br/>
密碼:<input name="gUser.password" id="gUser.password" type="password"/><br/>
<input name="login" type="submit" value="登錄"/></p>
</form>
Xwork.xml:
<action name="login" class="com.rambo.app.user.login.LoginAction">
<result name="success" type="redirect">
<param name="location">user/dirUser.action</param>
</result>
<result name="error" type="redirect">
<param name="location">doError.action</param>
</result>
<interceptor-ref name="defaultStack"/>
</action>
Java 端:
public class LoginAction extends ActionSupport{
private Integer sysId;
public GUser gUser = new GUser();
public LoginAction() {
}
public String execute() {
//業務處理......
return Action.SUCCESS;
}
//getter/setter......
}
2.4.2 modelStack 模型驅動攔截器
Xwork.xml 定義的 Action 在繼承 ActionSupport 類的同時需要實現 ModelDriven(模型驅動)介面中的 Object getModel()方法,通過這個方法返回的就是要接收的模型對象。
就可以直接將 jsp 表單數據轉換為 java 文件定義的相應對象。
如下麵 Java 示例中的 info 對象。註意:jsp 文件表單 input 中的 name 應該與 java 文件中 info 對象所對應 User 類中的屬性相對應。
前端:
<form name="form1" id="form1" action="editUserInfo.action" method="post">
<input type="hidden" name="id" id="id"/>
<div>郵箱:<input readonly name="email" id="email"/></div>
<div>姓名:<input name="realName" id="realName" /></div>
<div>電話:<input name="phone" id="phone"/></div>
<div><input type="submit" value="保存"/></div>
</form>
Xwork.xml:
<action name="editUserInfo" class="com.rambo.app.user.info.EditUserInfo">
<result name="success" type="dispatcher">
<param name="location">../resultjson.jsp</param>
</result>
<result name="error" type="dispatcher">
<param name="location">../resultjson.jsp</param>
</result>
<interceptor-ref name="modelStack"/>
</action>
Java 端:
public class EditUserInfo extends ActionSupport implements ModelDriven{
private GUser info = new GUser();
public Object getModel() {
return info;
}
public EditUserInfo() {
}
protected String execute() {
//業務處理.....
return Action.SUCCESS;
}
//getter/setter......
}
2.4.3 uploadStack 上傳攔截器
Xwork.xml 定義的 Action需要繼承 ActionSupport 類,通過文件上傳攔截器就可以自動將 jsp 表單數據及二 進位文件數轉換為 java 文件定義的相應變數各文件對象,如下麵示例中的 userId 和 uploadFile 對象。
註意:jsp 文件表單 input 中的 name 名要與 java 文件中的變數名相對應。
前端:
<form name="form1" action="uploadUserImg.action" method="post" ENCTYPE="multipart/form-data" >
<input type="hidden" name="userId" id="userId" value="1" />
上傳附件:<input type="file" name="uploadFile" id="uploadFile">
<input type="submit" value="上傳">
</form>
Xwork.xml:
<action name="uploadUserImg" class="com.rambo.app.user.info.UploadUserImg">
<result name="success" type="dispatcher">
<param name="location">../resultxml.jsp</param>
</result>
<result name="error" type="dispatcher">
<param name="location">../resultxml.jsp</param>
</result>
<interceptor-ref name="uploadStack"/>
</action>
Java 端:
public class UploadUserImg extends ActionSupport {
private Integer userId;
private File uploadFile;
public UploadUserImg() {
}
public String execute() {
if (uploadFile == null || userId == null)
return Action.ERROR;
//業務處理......
return Action.SUCCESS;
}
//getter/setter.....
}