JBuilder2005實戰JSP之切換控制
來源:互聯網
上載者:User
js|控制 由於在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的屬性中,同時完成類型轉換(只有基礎資料型別 (Elementary Data Type)或建構函式支援的才可以完成轉換)。在執行完第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頁面。