用ActionForm截獲登錄表單數據
原登錄模塊用bookstore.User描述login.jsp登錄頁面表單的數據,在switch.jsp程序中通過<jsp:useBean>標簽獲取login.jsp表單的數據。其實User類相當於Struts框架中的模型,我們將通過一個ActionForm更好地實現這個功能。
ActionForm和Bean一樣以屬性名匹配的映射機制從HTTP請求中填充對象數據,但ActionForm比一般的Bean提供了更多的功能,Struts允許ActionForm通過validate()方法進行自校驗,當數據不合法時自動轉向到輸出界面,此外還可以通過reset()方法,在數據填充前復位屬性值。
下面我們就來創建UserActionForm,替換User的功能,建立起Struts框架中的"數據模型"。
1.指定ActionForm的Web模塊及類信息
File->New...->Web->在Web頁中雙擊ActionForm圖標,彈出如圖6所示的對話框:
圖6 創建UserActionForm
·Struts config:我們前面有提到Struts1.1支持多個配置文件,所以你在這兒可以選擇使用哪個Struts配置文件。因為我們現在還沒有定義多個Struts配置文件,所以只得使用struts-config.xml。在開發新增圖書的功能時,我們將定義另一個配置文件。
·ActionForm:ActionForm的類名,這裡我們填入UserActionForm。
按Next到下一步。
2.定義ActionForm屬性
圖7 定義ActionForm屬性
通過Add...按鈕為UserActionForm增加4個屬性,如圖7所示。特別的,如果這個ActionForm所對應的入口頁面已經創建,你也可以直接通過Add from JSP...按鈕,選擇一個JSP頁面,JBuilder會分析這個頁面的表單,並將表單的數據組件名抽取為ActionForm的屬性。
按Next到下一步。
3.一些附加功能的定義
圖8 附加功能定義
在FormBeanName中為UserActionForm指定一個名字,一般接受JBuilder所提供的默認名即可。這個名字將在struts-config.xml文件用來命名UserActionForm。
ActionForm比一般JavaBean強大的地方在於它可以進行數據檢驗,還可以進行數據復位。如果這個ActionForm最終要放到session中的,那麼最好實現reset()方法,以復位ActionForm的數據,否則屬性可能不會反映最新的值。這裡, UserActionForm無需進行數據有效性校驗,但由於UserActionForm最終需要放到session中,所以我們需要實現reset()方法。故此我們勾選Create/replace reset() method body選項。
直接按Finish創建UserActionForm,再將User類的代碼拷貝過來,整改後的最終代碼如下所示:
代碼清單 6 以ActionForm實現的User類
1. package bookstore;
2.
3. import java.sql.*;
4. import java.text.*;
5. import java.util.Date;
6. import javax.servlet.http.*;
7. import org.apache.struts.action.*;
8.
9. public class UserActionForm
10. extends ActionForm
11. {
12. private String userId;
13. private String password;
14. private String userName;
15. private String loginDatetime;
16. public String getPassword() {
17. return password;
18. }
19.
20. …
21. //復位所有屬性值
22. public void reset(ActionMapping actionMapping,HttpServletRequest servletRequest) {
23. this.userId = null;
24. this.userName = null;
25. this.password = null;
26. this.loginDatetime = null;
27. }
此外,JBuilder自動在struts-conf.xml文件中通過<form-bean>描述ActionForm。UserActionForm必須和一個Action相關聯,因為HTTP請求通過Struts總控制器轉發給Action,Struts控制器一旦發現Action有一個對應的ActionForm時,就用HTTP請求的數據填充這個ActionForm。
用Action代替switch.jsp的控制轉換功能
我們在前面已經數落用switch.jsp實現請求轉換控制的缺點,Struts框架的Action是實現請求轉換控制的最適合替代者。
在這節裡,我們就來創建一個名為LoginAction的Action,讓其完美的接替switch.jsp的工作。
File->New...->Web->在Web頁中雙擊Action圖標,啟動創建Action的向導。
1.指定Action名字及Web模塊
圖9 指定Web模塊及Action名字
在Action中鍵入LoginAction作為Action的類名,其中Base class的下拉框中有許多Action基類可供選擇,它們用於不同的場合,這些選項是:
·org.apache.struts.action.Action:標准的Action。
·org.apache.struts.actions.ForwardAction:相當於JSP的<jsp:forward>,方便Struts控制器進行預處理。此外,從學究的角度上來說,在JSP頁面直接通過<jsp:forward>違反了MVC的分層原則,控制器無法干預。
·org.apache.struts.actions.IncludeAction:出於ForwardAction相似的原因,Struts推薦用IncludeAction代替JSP的<jsp:include>。
·org.apache.struts.actions.LookupDispatchAction:如果一個表單有多個提交按鈕,不同的提交按鈕執行不同的業務操作,用DispatchAction最為合適。
·org.apache.struts.actions.SwitchAction:用SwitchAction可在不同的Struts模塊間轉換。
由於我們的Action需要完成用戶密碼驗證的業務,並根據結果轉換到不同的頁面中,所以這個LoginAction是一個普通的Action,故我們選擇org.apache.struts.action.Action。
按Next到下一步。
2.設置Action的配置信息
圖10 設置LoginAction的配置信息
·Action path:訪問這個Action的URI,接受默認的/loginAction,這樣我們將通過類似這樣的URL:http://127.0.0.1:8080/webModule/loginAction.do來訪問這個Action。
·FormBean name:下拉框中列出Web模塊中所有的ActionForm,我們選擇前一小節中所創建的userActionForm。這樣客戶端的HTTP請求訪問LoginAction時,HTTP請求所帶的數據就會被Struts總控制器自動填充到userActionForm中了。
·Scope:Action有兩個選擇:request和session。表示ActionForm在填充後將放在request對象中還是session對象中,由於我們需要在通過密碼驗證後,才使用戶登錄系統。這樣就不能使userActionForm在數據填充時就放入session中,而應該在通過密碼驗證後,手工將其綁定到session中(UserActionForm一旦綁定到session中,其valueBound()方法就會被調用,記錄用戶登錄日志),故此,我們選擇request。
·input JSP:輸入的JSP頁面。在ActionForm需要進行數據有效性自校驗的情況下,如果校驗失敗,Struts框架總控制器將請求返回到這個輸入頁面上。因為UserActionForm無需進行有效性校驗(在3.1的第3步我們沒有為UserActionForm實現自校驗功能),所以無需指定輸入的JSP。
按Finish按鈕直接創建LoginAction,JBuilder自動打開Struts Config Editor,生動形象地展現用戶登錄模塊Struts框架下的處理流程,如圖11所示:
圖11 Struts Config Editor
位於中心的/loginAction是訪問LoginAction的URI,它是登錄業務的控制器。Struts總控制器創建一個UserActionForm實例,並用HTTP請求的數據填充UserActionForm實例,然後將其傳給LoginAction的execute()方法。
3.定義訪問入口
現在我們需要調整login.jsp表單的提交地址,使用LoginAction來處理用戶登錄的請求,調整後的代碼如所示:
代碼清單 7 login.jsp 使用LoginAction處理用戶登錄
1. <%@page contentType="text/html; charset=GBK" import="bookstore.UserList" %>
2. …
3. <form name="form1" method="post" action="/webModule/loginAction.do">用戶名:
4. <select name="userId">
5. <option value="" selected>--登錄用戶--</option>
6. <%=UserList.getUserListHTML()%>
7. </select>
8. 密 碼:
9. <input name="password" type="password">
10. <input type="submit" name="Submit" value="登錄">
11. </form>
12. </body>
13. </html>
如第3行所示,將原來action="switch.jsp"改為"/webModule/loginAction.do",由於我們需要將整個應用部署於/webModule的URI下,所以需要在Action訪問的地址前加上/webModule。如果通過Struts的<html:form>標簽來指定表單提交的地址,則無需添加/webModule,標簽將自動進行轉換,你將在本專題後續內容中學習到這種方法。
注意:
Struts框架總控制器Servlet通過路徑匹配的方式截獲HTTP請求,其匹配串是*.do,表示URL以.do結束的HTTP請求才會被Struts框架處理,否則Struts忽略之。所以在寫鏈接地址時千萬不要忘了調用地址後加一個.do的後綴。