在 struts 中使用動態 form,需要 有以下幾步:
1) 配置動態 form
要想使用動態 form, 首先要現在 struts-config.xml 中作配置
執行個體代碼如下:
< form-beans >
< form-bean name = "vOForm" type = "org.apache.struts.action.DynaActionForm" >
< form-property name = "uname" type = "java.lang.String" />
< form-property name = "upass" type = "java.lang.String" />
</ form-bean >
</ form-beans >
使用動態 form, 沒有對應的類,所以,如果需要擴充屬性,只需要再次設定檔中添加一個屬性家可以了。
但是如果是 actionform 的話,那麼,如果你添加了一個屬性的話,那麼你就要在屬性裡面添加一個屬性,在類裡面添加一個屬性。而必須做好這種對應。動態 form 就沒有這個必要了。
從這一點來說,動態 form 使用起來就更加方便。
2) 頁面 form
Form, 其實是一個 transfer object , 也就是說,是在 viewer 和 action 只見地交換資料和傳遞資料的對象。
所以從頁面的 form, 每一個屬性都要和動態 form 的屬性一一對應。
然後,由 struts 來完成其屬性值的映射。
執行個體代碼如下:
<form method="POST" action="login.do">
username : <input type="text" name="uname" value="zhangyi"><br>
password : <input type="password" name="upass" value="zhangyi"><br>
<input type="submit" name="submit" value="login">
</form>
這個 form 裡面的屬性和動態 form 裡面的屬性是一一對應的。
3) Action
由上面的頁面 form 上,我們可以看到,如果此 form 提交,那麼,請求提交到了 login.do
這個 action.
那麼,在這個 action 裡面,如何?對動態 form 的調用 ? 同普通的ActionForm一樣,Action類和JSP都可以訪問動態ActionForm,而訪問方式也基本一致。訪問動態ActionForm與訪問普通的ActionForm的最大區別在於對屬性的訪問方式不同。在標準的ActionForm中,針對每一個屬性都提供了getter和setter方法來讀取和設定屬性,而DynaActionForm把所有的屬性儲存在一個Map 對象中,因此訪問DyanActionForm中的屬性與訪問Map對象中的方法類似:
執行個體代碼如下:
DynaActionForm vOForm = (DynaActionForm) form;
String uname= (String)vOForm .get("uname");
String upass= (String)vOForm .getString("upass");
//vOForm.set("uname", "fengyan");設定值!
System. out .println( "vo is : " + vOForm);
因為,我們傳遞的是 DynaActionForm, 所以,在調用的時候,我們就要把 form 強制轉換成 DynaActionForm 對象。
4) 測試結果
上面粒子的執行結果如下:
vo is : DynaActionForm[dynaClass=vOForm,upass=bbbbbbbbb,uname=aaaaaaa]
也就是說,我們已經取得了此對象。
執行個體化動態ActionForm的解析
<form-bean name="logonForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="userName" type="java.lang.String"/>
<form-property name="password" type="java.lang.String"/>
<form-property name="forwardAction" type="java.lang.String"/>
</form-bean>
<action path="/logon" name="logonForm" input="/WEB-INF/jsp/bas/logon.jsp" scope="request" type="com.longtop.bas.web.LogonAction" validate="false"/>
FormBeanConfig ----- 和<form-bean>配置對應的類
protected ModuleConfig moduleConfig;
protected String name;
protected String type;
protected boolean dynamic = false;
protected HashMap formProperties = new HashMap();//和<form-property>相對應的屬性。
DynaActionFormClass ----專門用來處理動態類,這樣使用者就不用單獨定義ActionForm。
protected transient static HashMap dynaClasses = new HashMap();//static類型,所有DynaActionFormClass 執行個體的該變數都是一致的,且裡面存放的是DynaActionForm或DynaActionForm的子類。
protected transient Class beanClass = null;//該變數表示要建立的動態ActionForm的類名(org.apache.struts.validator.DynaValidatorForm)。
protected FormBeanConfig config = null;//和<form-bean>配置相對應的類,一個<form-bean>配置就會產生一個DynaActionFormClass 。
protected HashMap propertiesMap = new HashMap();//和<form-property>相對應的屬性集合。
protected DynaProperty properties[] = null;和<form-property>相對應的DynaProperty 數組。
protected String name = null;//和<form-bean>的name一致=config.getName()。
其中重要的方法有
public static DynaActionFormClass createDynaActionFormClass(FormBeanConfig config)
首先尋找該類的靜態集合dynaClasses 是否有和<form-bean>相對應的DynaActionFormClass執行個體。如果有,則返回這個DynaActionFormClass執行個體。如果沒有,則執行個體化一個DynaActionFormClass類,並初始化它的config變數, name變數,properties數組,propertiesMap 集合,並且載入config.getType()對應的類((org.apache.struts.validator.DynaValidatorForm)),最後將這個執行個體(DynaActionFormClass)添加到靜態變數dynaClasses 中。
public DynaBean newInstance()
執行個體化DynaActionFormClass上面載入的beanClass(org.apache.struts.validator.DynaValidatorForm), 設定 beanClass的DynaActionFormClass = this(DynaActionFormClass)和dynaValues(HashMap)屬性集合。
DynaActionForm---每個請求都要獲得或產生一個和地址相對應的<form-bean>,如果是動態form-bean,就一定是DynaActionForm或DynaActionForm的子類。
protected DynaActionFormClass dynaClass = null;//執行個體化該類的DynaActionFormClass
protected HashMap dynaValues = new HashMap();//和<form-property>相對應的DynaProperty 集合。
重要的方法有
(1)struts啟動的時候,在初始化moduleconfig(init()內的initModuleConfig())的過程中,載入動態類DynaActionFormClass。
ModuleConfig config = .............................;
// 獲得struts-config.xml文檔中配置的<form-bean>元素對應的FormBeanConfig對象,如果該<form-bean>的type是動態actionForm(type="org.apache.struts.validator.DynaValidatorForm"),則載入這個類。
FormBeanConfig fbs[] = config.findFormBeanConfigs();
for (int i = 0; i < fbs.length; i++) {
if (fbs[i].getDynamic()) {
DynaActionFormClass.createDynaActionFormClass(fbs[i]);
}
}
(2)如果有請求的地址是/WEB-INF/jsp/bas/logon.jsp,則該請求的過程從處理ActionMapping的環節開始如下:
1、ActionMapping mapping = processMapping(request, response, path);
通過尋找ModuleConfig的ActionConfig集合中和請求的path相對應的(struts啟動時,已經初始化了ModuleConfig的ActionConfig集合)。如果有尋找該ActionMapping對象,則添加到request對象中。如果沒有的話,該請求就交給系統預設的ActionMapping(<action>的unknown = "true")。
2、 ActionForm form = processActionForm(request, response, mapping);
如果<action>配置沒有name屬性或name屬性沒有對應的<form-bean>元素,則退出。或則通過尋找ModuleConfig的FormBeanConfig集合中和ActionMapping的name屬性相對應的FormBeanConfig。根據<action>的name屬性尋找request或session是否有相應的ActionForm(attribute)。如果有,則返回這個ActionForm執行個體。如果沒有,執行下一步。
3、如果判斷<action>的dynamic屬性是否為true,先執行個體化一個DynaActionFormClass。
DynaActionFormClass dynaClass = DynaActionFormClass.createDynaActionFormClass(config);
首先尋找該類的靜態集合dynaClasses 是否有和<form-bean>相對應的DynaActionFormClass執行個體。如果有,則返回這個DynaActionFormClass執行個體。如果沒有,則執行個體化一個DynaActionFormClass類,並初始化它的config變數, name變數,properties數組,propertiesMap 集合,並且載入config.getType()對應的類((org.apache.struts.validator.DynaValidatorForm))到beanClass變數中,最後將這個執行個體(DynaActionFormClass)添加到靜態變數dynaClasses 中。
DynaActionFormClass dynaClass =
(DynaActionFormClass) dynaClasses.get(key);
if (dynaClass == null) {
dynaClass = new DynaActionFormClass(config);
dynaClasses.put(key, dynaClass);
}
return (dynaClass);
4、執行個體化一個動態ActionForm。
ActionForm instance = null;
instance = (ActionForm) dynaClass.newInstance();執行個體化3步驟載入的類。
執行個體化DynaActionFormClass上面載入的beanClass(org.apache.struts.validator.DynaValidatorForm), 初始化 beanClass的DynaActionFormClass = this(DynaActionFormClass)和dynaValues(HashMap)屬性集合的初始值。
5、初始化ActionForm的property屬性的初始值。
public void initialize(ActionMapping mapping);
<form-property name="userName" type="java.lang.String" initial="hh"/>
6、以下的處理和正常的請求處理一致。