鄙人一點對struts1.2中ActionForm的理解

轉自:http://hi.csdn.net/space-62502-do-thread-id-4019.html   本人覺得總結的不錯,也收藏學習下。
初學struts的人我認爲首先應該把struts1.2學精,何爲精,就是明白struts的控制流程以及它核心API的實現原理(比如Action/DispatchAction/MappingDispatchAction/LookupDispatchAction/ActionForm的實現原理)然後自己會寫一個“山寨版”的struts1.2,只有到達這樣的程度你才能深刻體會struts1.2的MVC,也才證明你學會了struts1.2,當你再學習struts2.0的時候會非常的容易,那麼玩轉struts1.2的關鍵就是能夠玩轉ActionForm,在此我把自己學習struts1.2時ActionForm的使用及其實現原理貼出來曬一曬,還望各位不要見笑,給些意見。
 
ActionForm的應用
(一)、ActionForm的特性
1.創建一個form類必須繼承於四個父類中的一個,要麼繼承ActionForm,要麼繼承ValidatorForm,要麼繼承ValidatorActionForm,要麼繼承
2.一個form類中的每一個屬性都將和頁面中form表單中的每一個表單元素一一對應
Example:
一個表單爲:
<form>
 <input type="text" name="username"></input>
 <input type="password" name="password"></input>
 <input type="text" name="email"></input>
</form>
一個與之對應的form類
public class UserForm extends ActionForm{
  private String username;
  private String password;
  private String email;
  private String address;
  
  //下面省略getter和setter方法
}
一個引用了該form類的appAction:
<form-beans>
 <form-bean name="userForm" type="form.UserForm"></form-bean>
</form-beans>
<action-mappings>
<action path="/test" type="action.TestAction" name="userForm" attribute="uf" scope="request"></action>
</action-mappings>
3.在引用了form-bean的action中name屬性的值就是form-bean中name的值
4.這個userForm默認會被放在session中,使用scope可以指定存儲該form對象的地方,自然attribute就是用來給存放在該範圍中的form對象起的別名,如果不設置attribute
屬性那麼attribute默認的就使用name的值
(二)、普通HTML表單使用Form的工作原理
ActionServlet對struts-config進行解析時,當解析到某個action中存在一個屬性name,那麼ActionServlet中的RequestProcessor就會根據該name的值找到對應的form-bean然後創建一個對應的form類實例,放在我們定義的存儲範圍中,當表單提交到該action對應的appAction之前也就是到達FC的時候,FC會做以下事情
1.根據路徑找到對應的內存中存放着的配置對象中的action
2.根據action中的attribute屬性,從session中得到一個對應的form實例
3.該form實例調用reset方法對自己進行清空
4.用表單中的值去填充該form實例
5.如果要該form要進行驗證那麼就該form就會調用validate方法按照我們規定的驗證規則進行驗證
(三)、struts表單使用Form的工作原理
1.利用struts的HTML標籤庫定義的HTML元素其實是服務器端的java代碼,java代碼是編譯型代碼而HTML則是解釋型代碼,所以在使用struts的HTML標籤庫定義的HTML元素要更加的嚴謹,只要某個元素甚至是某個屬性沒有定義對,那麼編譯就不能通過從而拋出異常,例如在使用struts的HTML標籤庫定義表單的時候action屬性是在編譯的時就要被確定的如果action屬性所定義的提交路徑是空或者是錯誤,那麼服務器在編譯的時候就會拋出500的異常,而不像普通HTML表單action屬性是在提交的時候才確定的
2.原理跟普通HTML表單使用Form的工作原理大同小異,不同在於當服務器對form表單進行編譯的時候會向action所指定的地址發一個請求,看是否正確,所以這個時候其實就已經提交了一次表單,當表單到達FC的時候跟上面做的幾件事情中就第三件不同,不同在於表單和form中的值都將互相填充,這就是struts對錶單的回添機制
Example:
表單爲:
//先導入struts的html標籤庫
<html:form action="test.do" method="post">
 <html:text property="username"></html:text>
 <html:text property="salary"></html:text>
 中文<html:multibox property="lang" value="zh"></html:multibox>
 英文<html:multibox property="lang" value="en"></html:multibox>
 俄語<html:multibox property="lang" value="ey"></html:multibox>
 <html:submit value="click me"></html:submit>
</html:form>
form類爲:
public class UserForm extends ActionForm{
 private String username;
 private double salary=1000.00;
 private String[] lang;
 
 //省略getter和setter方法
}
配置文件爲:
<form-beans>
 <form-bean name="userForm" type="form.UserForm"></form-bean>
</form-beans>
<action-mappings>
 <action path="/test" type="action.TestAction" name="userForm" attribute="uf">
  <forward name="success" path="/show.do"></forward>
 </action> 
 <action path="/show" type="action.ShowAction" >
  <forward name="success" path="/test.do"></forward>
 </action>
</action-mappings>
經驗:
1.顯示頁面之前服務器會向text.do發送一次請求,該請求也就是提交表單
2.當上面的請求到FC的時候會用form中的值去填充這個表單然後回顯給用戶所以用戶看到的頁面顯示結果是salary文本框中有一個值爲1000
3.當用戶再次提交表單,請求到達FC的時候服務器會首先檢查你所提交的表單元素的值跟session中這個form與之對應的屬性的值是否相同,如果相同就直接利用該form去填充表單,如果不相同就先把提交的表單元素的值賦給form中與之對應的屬性再利用form去填充表單
4.該實例有一個問題,就是當用戶第一次選擇了兩種語言,然後提交,第二次用戶一種語言都沒選,然後提交,這時候回顯的結果出人意料,複選框中的值既然是第一次用戶所選擇的值,原因是,複選框有一個特性,如果用戶什麼都不選擇,那麼提交表單的時候就不提交複選框,如果我們使用get請求提交的話就能明顯的看到這種情況表單提交的屬性只有username和salary兩個,這兩個元素即使沒有值也會提交,就因爲這一點,當表單到達FC的時候,服務器只看到提交的兩個表單元素username和salary,然後檢查form中的屬性也只會檢查username和salary兩個,而不會檢查lang,如果表單中的username和salary與form中與之對應的username和salary屬性不一樣,那麼就先把表單中的username和salary值賦給form中的username和salary屬性,然後利用form去填充表單,如果一樣,那麼就利用原來的form去填充表單,在這兩種情況下form中的lang屬性都將不會被檢查更不用提改變,所以lang用的還是上一次的值,自然回顯的時候form中的複選框的值就是上一次的值
5.解決這一問題可以有兩種辦法,在提交表單以後就把session中的form對象給刪除掉,每一次提交都新創建一個form對象也就是在頁面的末尾加一個
<%session.removeAttribute("uf")%>
第二種解決辦法是在UserForm中覆蓋父類的reset方法,該reset方法將在form填充之前做,這樣我們就能在reset中把我們想要復位的屬性先復位
當然利用第二種是最好的
5.我們可以利用struts的form回添機制進行回添操作,回添的時機是在form到達頁面之前,可以在Action中來做也可以在reset中來做
(四)、Form與實體對象之間的關係
有的時候我們爲了方便會把取到的form中的值直接拷貝到實體對象中去然後把實體對象再存儲到數據庫中,這樣給我們的編程帶來了很多的方便,但前提是實體對象中需要拷貝的屬性,form中要拷貝過去的屬性,與form對應的表單元素他們三者必須一一對應.這樣我們就可以把表單中的值得到封裝到form中然後再把form中與實體對象中屬性相同的值拷貝到實體對象中
Example:
entity:
public class User{
 private String name;
 private String password;
 private double salary;
 private String address;
 //省略getter和setter方法
}
form:
public class UserForm{
 private String name;
 private String password;
 private String salary;
 //省略getter和setter方法
}
表單:
<form>
 <input type="text" name="name"></input>
 <input type="password" name="password"></input>
 <input type="text" name="salary"></input>
</form>
1.把表單中的值賦值給UserForm
2.把UserForm中的值拷貝到User對象中:
//下面這條語句是在action的某個方法中做的所以form直接可以用
BeanUtils.copyProperties(user,form);
3.將user對象存放在數據庫中
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章