JBuilder2005實戰JSP之切換控制(3)
作者:Eve Cole
更新時間:2009-07-02 17:10:13
由於在login.jsp的表單中透過action屬性指定switch.jsp為回應的JSP文件,當用戶在login.jsp中選定登入用戶,輸入密碼提交表單後,客戶端將向伺服器發送HTTP請求,伺服器即呼叫switch.jsp來回應這個請求。
表單中使用者名稱和密碼兩個元件的資料會透過HTTP請求傳給伺服器的switch.jsp,伺服器將這些資訊封裝在request物件中傳給switch.jsp,所以switch.jsp可透過request.getParameter(String paraName)來取得這兩個值。
String userId = request.getParameter("userId"); String password = request.getParameter("password"); |
試想如果login.jsp的表單有10個以上的資料元件,則在switch.jsp中必須透過對應數目的request.getParameter()方法取得其值。此外,如果這些資料不是字段字串類型,而是整數或浮點數,由於request.getParameter()方法傳回的值都是String,也必須進行類型的轉換,這種工作不但單調乏味,還容易出錯。
JSP允許你透過Bean以映射的方式接收網頁表單的數據,Bean以這個規則映射表單的數據:Bean屬性名=表單數據組件名,也即所有和Bean屬性名相同的表單數據域被自動填充到Bean中,並且完成資料類型的轉換。如login.jsp的表單中有兩個資料元件,一個名為userId,另一個是password,定義一個擁有相同名稱的userId和password屬性的User.java Bean,這個Bean將可以自動接收表單中的兩個數據組件值。
編寫User.java
我們先來寫這個User.java的Bean,在工程中建立User.java,其程式碼如下所示:
程式碼清單7 User.java
1. package bookstore; 2. 3. public class User 4. { 5. private String userId;//用戶Id 6. private String password;//密碼 7. private String userName;//用戶名 8. public String getPassword() { 9. return password; 10. } 11. public String getUserId() { 12. return userId; 13. } 14. public String getUserName() { 15. return userName; 16. } 17. public void setPassword(String password) { 18. this.password = password; 19. } 20. public void setUserId(String userId) { 21. this.userId = userId; 22. } 23. public void setUserName(String userName) { 24. this.userName = userName; 25. } 26. } |
除userId和password兩屬性名,還有一個用戶名屬性userName,這個屬性的值不是從login.jsp的表單接收的,當用戶名密碼驗證正確後,從數據表T_USER表中獲取用戶名保存在這個屬性中,以便其他地方引用,保存並編譯這個類別。
提示:
你可以透過JBuilder的Bean Express工具快速建立User.java的程式碼,在一般情況下,你應該透過Bean Express來建立Bean的屬性,這樣不但自動產生get/set的屬性存取方法,還保證了Bean命名規範。 |
編寫頁面程式
在建立User.java 的Bean後,我們著手建立switch.jsp,在switch.jsp中引用這個Bean。
透過File->New..->Web->雙擊JSP圖示啟動建立JSP精靈。
1.指定swith.jsp名字
圖10 指定switch.jsp的名字 |
一直按Next到精靈的第3步。
2.引用User.java Bean
圖11 指定JSP中引用Bean |
點選Add Bean...按鈕,彈出Select a Class對話框,在對話框中選擇bookstore.User類,如下圖:
圖12 選擇類別作為Bean |
按OK後,返回精靈步驟3的對話框,此時對話框的Bean清單中多了一行記錄,可以在ID欄中為Bean指定一個名字,在Scope中指定Bean的作用域,如下圖所示:
圖13 引用一個Bean |
我們為User的Bean取名為userBean,將其作用域設定為page域。 page域即為頁面作用域,在目前頁面範圍作用域內可用,當JSP回傳回應,或請求轉到其他的JSP頁面時,都不可用了,其他3個作用域說明如下:
·request作用域:當一個請求產生直到回傳回應的範圍內都是有效的,如a.jsp中宣告為request作用域的Bean,當a.jsp透過<jsp:forward>轉移請求到b .jsp頁面中時還是可用的。
·session作用域:在使用者會話的週期內都是可用的,會話週期為使用者登入系統直到其退出系統為此。
·application作用域:這個作用域最長,表示Web容器啟動直到關閉都是有效的。
按Next到下一步。
3.設定運行配置項
在精靈的最後一步,你可以為創建的JSP產生一個運行配置項,雖然嚮導將創建一個運行配置項設置為默認選項,但筆者認為這並不是一個合理的默認值,建議取消create a runtime configuration設置項,不要建立JSP的運行配置項,如下圖所示:
按Finish按鈕建立switch.jsp文件,其程式碼如下所示:
程式碼清單8 精靈建立的switch.jsp
1. <%@ page contentType="text/html; charset=GBK" %> 2. <html> 3. <head> 4. <title> 5. switch 6. </title> 7. </head> 8. <jsp:useBean id="userBean" scope="page" class="bookstore.User" /> 9. <jsp:setProperty name="userBean" property="*" /> 10. <body bgcolor="#ffffff"> 11. <h1> 12. JBuilder Generated JSP 13. </h1> 14. </body> 15. </html> |
第8行是引用Bean的JSP標籤,第9行用表單的資料填入Bean的屬性值,也就是以名字匹配的方式將request的參數填入Bean的屬性中,同時完成型別轉換(只有基本資料型別或構造函數支援的才可以完成轉換)。在執行完第9行後,userBean中的userId和password屬性將會被設定為login.jsp頁面中所傳送過來的使用者名稱和密碼的值。
因為switch.jsp只是用來控制,並不需要顯示內容到客戶端,所以我們去掉switch.jsp中的HTML程式碼,將switch.jsp調整為:
程式碼清單9 移除靜態HTML程式碼後的switch.jsp
1. <%@ page contentType="text/html; charset=GBK" %> 2. <jsp:useBean id="userBean" scope="page" class="bookstore.User" /> 3. <jsp:setProperty name="userBean" property="*" /> |
在switch.jsp中提供一段Scriptlet,將userId和password傳送到資料庫和T_USER表中的用戶比較看是否是合法的用戶,根據驗證的結果轉向不同的頁面。 switch.jsp的最終程式碼如下所示:
程式碼清單10 最終的switch.jsp
1. <%@page contentType="text/html; charset=GBK"%> 2. <%@page import="bookstore.*"%> 3. <%@page import="java.sql.*"%> 4. <jsp:useBean id="userBean" scope="session" class="bookstore.User"/> 5. <jsp:setProperty name="userBean" property="*"/> 6. <% 7. Connection conn = null; 8. try { 9. conn = DBConnection.getConnection(); 10. PreparedStatement pStat = conn.prepareStatement( 11. "select USER_NAME from T_USER where USER_ID=? and password = ?"); 12. pStat.setString(1, userBean.getUserId()); 13. pStat.setString(2, userBean.getPassword()); 14. ResultSet rs = pStat.executeQuery(); 15. if (rs.next()) { //密碼正確 16. userBean.setUserName(rs.getString(1));//設定使用者名 17. session.setAttribute("ses_userBean", userBean);//將userBean放入Session物件中 18. %><jsp:forward page=" welcome.jsp "></jsp:forward> 19. <%} else { //密碼錯誤%> 20. <jsp:forward page="fail.jsp"></jsp:forward> 21. <% 22. }} finally { 23. if(conn != null) conn.close(); 24. } 25. %> |
·在第2~3行中引入Scriptlet程式碼中所需的類別。
·第7~14行程式碼傳送查詢SQL語句給資料庫並傳回結果。
·第15行透過檢查結果集的記錄數間接判斷使用者密碼是否正確。
·第16~18行是使用者密碼正確的回應代碼,先用結果集的USER_NAME屬性填入userBean的userName屬性值,然後將userBean物件放入Session中,最後轉向welcome.jsp頁面。
·當使用者輸入密碼不正確時,結果集中將沒有記錄,此時rs.next()回傳false,程式轉向第20行,第20行的程式碼將頁面轉向到密碼輸入錯誤的處理頁面fail.jsp。
·第22~24行的程式碼用於關閉資料庫的連線。
也許大家已經發現雖然第9~21行會拋出SQLException異常,但我們並沒有對應的異常捕獲區塊,在標準的Java程式中會導致一個編譯期的錯誤,但在JSP中卻可以順序通過編譯,這是因為JSP頁面本身會捕捉頁面中拋出的所有例外。
假設第11行的SQL查詢語句發生錯誤,如將使用者表名誤寫為User(正確為T_USER),當switch.jsp被呼叫後,第14行將拋出SQLException異常,此時switch.jsp將顯示出異常堆疊跡的追蹤資訊頁面,如下圖如示:
圖14 可怕的錯誤處理頁面 |
上圖所示的錯誤處理頁面可謂青面獠牙,面目猙獰,非常不友好,對於開發人員來說這種報錯頁面也許是適合的,因為它提供了許多錯誤跟踪信息,但最終用戶是不可能接受這種粗野的出錯頁面的。 JSP允許你透過<%@ page errorPage%>為頁面指定一個專門處理錯誤的JSP頁面,以便用一種友善、直覺的形式展現錯誤。在下一節裡,我們將建立一個用於處理錯誤的JSP頁面,在建立之後,我們再來為switch.jsp指定錯誤處理JSP頁面。