- Java Web開發實例大全(基礎卷) (軟件工程師開發大系)
- 軟件開發技術聯盟
- 10380字
- 2021-03-26 13:01:23
4.2 JSP內置對象
JSP為了簡化開發,提供了一些內置對象,用來實現很多JSP應用。在使用JSP內置對象時,不需要先定義這些對象,直接使用即可。JSP提供了request、response、session、application、out、page、config、exception和pageContent 9個內置對象。其中request對象、response對象、out對象、page對象、config對象、exception對象和pageContent對象的有效范圍是當前頁面,而session對象的有效范圍是當前會話,即同一個客戶端的所有頁面;application對象的有效范圍是當前應用,即在同一個應用程序中,只要服務器不關閉,這個對象就有效。
JSP內置對象是應用JSP進行Web開發時經常被使用的技術。通過它們可以對Web開發中的請求、響應、會話、應用、輸出、配置信息和異常信息等內容進行控制。對于不同的內容將由不同的內容進行控制。下面將介紹各內置對象的使用場合。
實例102 獲取表單提交的信息
光盤位置:光盤\MR\04\102
初級
實用指數:
實例說明
在Web應用程序中,經常需要完成用戶與網站的交互。例如,當用戶填寫表單后,需要把數據提交給服務器處理,這時服務器就需要獲取這些信息。本實例將介紹如何獲取表單提交的信息。運行本實例,如圖4.9所示,輸入用戶注冊信息,單擊“注冊”按鈕后,在JSP處理頁中將獲取到這些表單數據,并將其顯示在頁面中,如圖4.10所示。

圖4.9 用戶注冊表單頁

圖4.10 獲取用戶注冊信息
關鍵技術
JSP的內置對象request封裝了由客戶端生成的HTTP請求的所有細節,主要包括HTTP頭信息、系統信息、請求方式和請求參數等。通過request對象提供的相應方法可以處理客戶端瀏覽器提交的HTTP請求中的各項參數。
在本實例中,通過request對象的getParameter()方法可以獲取用戶提交的表單信息。例如,存在一個name屬性為username的文本框,在表單提交后,要獲取其value值,可以通過下面的代碼實現:
String userName = request.getParameter("username");
參數username與HTML表單的name屬性對應,如果參數值不存在,則返回一個null值,該方法的返回值為String類型。
設計過程
(1)創建用戶注冊的表單頁index.jsp。
(2)創建save.jsp頁面,在該頁面中獲取用戶提交的表單信息并顯示在頁面中,關鍵代碼如下:
<% request.setCharacterEncoding("UTF-8"); String name=request.getParameter("name"); String sex = request.getParameter("sex"); String age = request.getParameter("age"); String email=request.getParameter("email"); %> <table height="150"width="300"> <tr><td align="center"colspan="4"height="20"></td></tr> <tr><td align="center"colspan="4">獲取表單信息</td></tr> <tr> <td>用戶名:</td> <td> <%if(name==null||"".equals(name)){ out.println(""); }else{ out.println(name); } %> </td> </tr> <tr> <td>性別: </td> <td> <%if(sex==null||"".equals(sex)){ out.println(""); }else{ out.println(sex); } %> </td> </tr> <tr> <td>年齡:</td> <td> <%if(age==null||"".equals(age)){ out.println(""); }else{ out.println(age); } %> </td> </tr> <tr> <td>Email: </td> <td> <%if(email==null||"".equals(email)){ out.println(""); }else{ out.println(email); } %> </td> </tr> <tr><td align="center"colspan="4"height="20"></td></tr> </table>
秘笈心法
在獲取表單請求參數時,很容易發生亂碼問題,這時,需要在應用request獲取請求參數之前,調用request對象的setCharacterEncoding()方法設置請求編碼。需要注意的是,這個編碼是根據表單頁的編碼格式而定的,如表單頁的編碼格式為UTF-8,那么在處理頁中應該調用如下代碼:
request.setCharacterEncoding("UTF-8");
實例103 獲取訪問請求參數
光盤位置:光盤\MR\04\103
初級
實用指數:
實例說明
在Web應用程序中,有時需要通過超鏈接來傳遞參數。假定在顯示員工信息的頁面中,每行員工信息都包含一個“刪除”的超鏈接,然后在這個超鏈接中需要指定用戶ID為參數,當單擊“刪除”超鏈接時,在處理頁中需要獲取用戶ID值,最后根據用戶ID刪除員工信息。本實例將介紹如何獲取超鏈接訪問的請求參數,實例運行結果如圖4.11所示。

圖4.11 處理頁的運行結果
關鍵技術
request對象用于處理HTTP請求中的各項參數。在這些參數中,最常用的就是獲取訪問請求參數。當通過超鏈接的形式發送請求時,可以為該請求傳遞參數,這可以通過在超鏈接的后面加上問號?來實現。注意這個問號為英文半角的符號。例如,發送一個請求到delete.jsp頁面,并傳遞一個名稱為id的參數,可以通過以下超鏈接實現:
<a href="delete.jsp? id=1">刪除</a>
設計過程
(1)創建index.jsp文件,在該文件中添加一個用于鏈接到deal.jsp頁面的超鏈接,并傳遞兩個參數。index. jsp文件的具體代碼如下:
<%@page language="java"contentType="text/html;charset=GB18030"pageEncoding="GB18030"%> <html> <head> <meta http-equiv="Content-Type"content="text/html;charset=GB18030"> <title>使用request對象獲取請求參數值</title> </head> <body> <a href="deal.jsp? id=1&user=">處理頁</a> </body> </html>
(2)創建deal.jsp文件,在該文件中通過request對象的getParameter()方法獲取請求參數id、user和pwd的值并輸出。deal.jsp文件的具體代碼如下:
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <% String id=request.getParameter("id"); //獲取id參數的值 String user=request.getParameter("user"); //獲取user參數的值 String pwd=request.getParameter("pwd"); //獲取pwd參數的值 %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=GB18030"> <title>處理頁</title> </head> <body> id參數的值為:<%=id%><br> user參數的值為:<%=user%><br> pwd參數的值為:<%=pwd%> </body> </html>
秘笈心法
在通過問號“?”來指定請求參數時,參數值不需要使用單引號或雙引號括起來,包括字符型的參數。可以同時指定多個參數,各參數間用符號“&”分隔即可。
實例104 將表單請求提交到本頁
光盤位置:光盤\MR\04\104
初級
實用指數:
實例說明
在Web應用程序中,有時需要將表單請求提交到本頁進行處理。本實例將介紹如何將表單請求提交到本頁。運行本實例,如圖4.12所示,輸入用戶名和密碼,單擊“登錄”按鈕,將在本頁直接獲取到用戶名和密碼,并顯示在頁面中。

圖4.12 將表單請求提交到本頁
關鍵技術
實現將表單提交到本頁,實際上很簡單,只要將表單<form>的action屬性設置為本頁即可,假定表單頁為index.jsp,那么action的值就應該為index.jsp,然后同樣應用request對象的getParameter()方法來獲取表單元素的值。
設計過程
(1)創建表單頁index.jsp,并設置將表單信息提交到本頁,關鍵代碼如下:
<form action="index.jsp"method="post"> <table height="150"width="300"> <tr><td align="center"colspan="4"height="20"></td></tr> <tr><td align="center"colspan="4">用戶登錄</td></tr> <tr> <td>用戶名: </td> <td><input type="text"name="name"/></td> </tr> <tr> <td>密碼: </td> <td><input type="password"name="pwd"/></td> </tr> <tr> <td></td> <td><input type="submit"value="登錄"/></td> </tr> <tr> <td>用戶名參數為:</td> <td><%=name %></td> </tr> <tr> <td>密碼參數為:</td> <td><%=pwd %></td> </tr> <tr><td align="center"colspan="4"height="20"></td></tr> </table> </form>
(2)在index.jsp頁中獲取表單信息,關鍵代碼如下:
<% request.setCharacterEncoding("UTF-8"); String name = request.getParameter("name"); String pwd = request.getParameter("pwd"); %>
秘笈心法
需要注意的是,在本實例的頁面中使用request對象的getParameter()方法來獲取參數時,在頁面被加載后就會自動執行這段代碼,因此,在本實例中需要進行合理的判斷,只有提交表單后才可以執行request對象的getParameter()方法來獲取表單的代碼。針對這一特點,可以在表單的“提交”按鈕中添加一個name屬性,以本實例為例,在“登錄”按鈕的標簽中添加name屬性,代碼如下:
<input type="submit" name="submit" value="注冊">
然后在獲取表單的請求信息之前,判斷用戶是否單擊了“登錄”按鈕,只有“登錄”按鈕的值不為null時,才繼續執行,代碼如下:
<% if( request.getParameter("submit")! =null ){ request.setCharacterEncoding("UTF-8"); String name = request.getParameter("name"); String pwd = request.getParameter("pwd"); } %>
實例105 通過request對象進行數據傳遞
光盤位置:光盤\MR\04\105
初級
實用指數:
實例說明
在進行請求轉發時,需要把一些數據傳遞到轉發后的頁面進行處理。這時,就需要使用request對象的setAttribute()方法將數據保存到request范圍內的變量中。本實例將介紹如何應用request對象進行數據傳遞,運行本實例,將顯示如圖4.13所示的運行結果。

圖4.13 本實例的運行結果
關鍵技術
request對象可以視為一個域,可以應用setAttribute()方法向域范圍內存放數據。request對象的setAttribute()方法的語法格式如下:
request.setAttribute(String name, Object object);
參數說明
? name:表示變量名,為String類型,在轉發后的頁面取數據時,就是通過這個變量名來獲取數據的。
? object:用于指定需要在request范圍內傳遞的數據,為Object類型。
在將數據保存到request范圍內的變量中后,可以通過request對象的getAttribute()方法獲取該變量的值,具體的語法格式如下:
request.getAttribute(String name);
參數說明
name:表示變量名,該變量名在request范圍內有效。
設計過程
(1)創建index.jsp文件,在該文件中,首先應用Java的try…catch語句捕獲頁面中的異常信息,如果沒有異常,則將運行結果保存到request范圍內的變量中;如果出現異常,則將錯誤提示信息保存到request范圍內的變量中,然后應用<jsp:forward>動作指令將頁面轉發到deal.jsp頁面。index.jsp文件的具體代碼如下:
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=GB18030"> <title>Insert title here</title> </head> <body> <% try{ //捕獲異常信息 int money=100; int number=0; request.setAttribute("result", money/number); //保存執行結果 }catch(Exception e){ request.setAttribute("result", "很抱歉,頁面產生錯誤!"); //保存錯誤提示信息 } %> <jsp:forward page="deal.jsp"/> </body> </html>
(2)創建deal.jsp文件,在該文件中通過request對象的getAttribute()方法獲取保存在request范圍內的變量result并輸出。這里需要注意的是,由于getAttribute()方法的返回值為Object類型,所以需要調用其toString()方法將其轉換為字符串類型。deal.jsp文件的具體代碼如下:
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=GB18030"> <title>結果頁</title> </head> <body> <%String message=request.getAttribute("result").toString(); %> <%=message %> </body> </html>
秘笈心法
由于應用setAttribute()方法保存在request對象中的數據類型為Object,因此,在實現一些數據的傳遞時,可以將類的對象保存在request中。假定有一個保存用戶注冊信息的User類對象,可以將這個對象保存在request中進行傳遞,然后在獲取User對象時需要進行類型強制轉換,將Object類型轉換為User類型,代碼如下:
User user = (User)request.getAttribute("user");
實例106 通過cookie保存并讀取用戶登錄信息
光盤位置:光盤\MR\04\106
初級
實用指數:
實例說明
在互聯網中,cookie是小段的文本信息,在網絡服務器上生成,并發送給瀏覽器。通過使用cookie可以標識用戶身份,記錄用戶名和密碼,跟蹤重復用戶等。瀏覽器將cookie以key/value的形式保存到客戶機的某個指定目錄中。運行本實例,第一次顯示的頁面如圖4.14所示;輸入姓名mr,并單擊“確定”按鈕后,將顯示如圖4.15所示的運行結果。

圖4.14 第一次運行的結果

圖4.15 第二次運行的結果
關鍵技術
通過cookie的getCookies()方法可獲取所有cookie對象的集合,通過cookie對象的getName()方法可獲取指定名稱的cookie,通過getValue()方法可獲取cookie對象的值。另外,將一個cookie對象發送到客戶端使用了response對象的addCookie()方法。
設計過程
(1)創建index.jsp文件,在該文件中首先獲取cookie對象的集合,如果集合不為空,就通過for循環遍歷cookie集合,從中找出設置的cookie(這里設置為mrCookie),并從該cookie中提取出用戶名和注冊時間,再根據獲取的結果顯示不同的提示信息。index.jsp文件的具體代碼如下:
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <%@ page import="java.net.URLDecoder" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=GB18030"> <title>通過cookie保存并讀取用戶登錄信息</title> </head> <body> <% Cookie[]cookies=request.getCookies(); //從request中獲得Cookie對象的集合 String user=""; //登錄用戶 String date=""; //注冊的時間 if (cookies ! = null) { for(int i=0; i<cookies.length; i++){ //遍歷cookie對象的集合 if(cookies[i].getName().equals("mrCookie")){ //如果cookie對象的名稱為mrCookie user=URLDecoder.decode(cookies[i].getValue().split("#")[0]); //獲取用戶名 date=cookies[i].getValue().split("#")[1]; //獲取注冊時間 } } } if("".equals(user)&&"".equals(date)){ //如果沒有注冊 %> 游客您好,歡迎您初次光臨! <form action="deal.jsp" method="post"> 請輸入姓名:<input name="user" type="text" value=""> <input type="submit" value="確定"> </form> <% }else{ //已經注冊 %> 歡迎[<b><%=user %></b>]再次光臨<br> 您注冊的時間是:<%=date %> <% } %> </body> </html>
(2)編寫deal.jsp文件,用于向cookie中寫入注冊信息。deal.jsp文件的具體代碼如下:
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <%@ page import="java.net.URLEncoder" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=GB18030"> <title>寫入cookie</title> </head> <body> <% request.setCharacterEncoding("GB18030"); //設置請求的編譯為GB18030 String user=URLEncoder.encode(request.getParameter("user"), "GB18030"); //獲取用戶名 Cookie cookie = new Cookie("mrCookie", user+"#"+new java.util.Date().toLocaleString()); //創建并實例化cookie對象 cookie.setMaxAge(60*60*24*30); //設置cookie有效期30天 response.addCookie(cookie); //保存cookie %> <script type="text/javascript">window.location.href="index.jsp"</script> </body> </html>
秘笈心法
在向cookie保存的信息中,如果包括中文,則需要調用java.net.URLEncoder類的encode()方法將要保存到cookie中的信息進行編碼;在讀取cookie的內容時,還需要應用java.net.URLDecoder類的decode()方法進行解碼。這樣,就可以成功地向cookie中寫入中文信息。
實例107 實現重定向頁面
光盤位置:光盤\MR\04\107
初級
實用指數:
實例說明
運行本實例,默認執行的是index.jsp頁面,在該頁面中,又執行了重定向頁面到login.jsp的操作,所以在瀏覽器中將顯示如圖4.16所示的用戶登錄頁面。

圖4.16 實現重定向頁面
關鍵技術
使用response對象提供的sendRedirect()方法可以將網頁重定向到另一個頁面。sendRedirect()方法的語法格式如下:
response.sendRedirect(String path);
參數說明
path:用于指定目標路徑,可以是相對路徑,也可以是不同主機的其他URL地址。
例如,使用sendRedirect()方法重定向網頁到login.jsp頁面(與當前網頁同級)和明日編程詞典網(與該網頁不在同一主機)的代碼如下:
response.sendRedirect("login.jsp"); //重定向到login.jsp頁面 response.sendRedirect("www.mrbccd.com"); //重定向到明日編程詞典網
設計過程
(1)創建index.jsp文件,在該文件中調用response對象的sendRedirect()方法重定向頁面到用戶登錄頁面login.jsp。index.jsp文件的關鍵代碼如下:
<%@page language="java"contentType="text/html;charset=GB18030"pageEncoding="GB18030"%> <%response.sendRedirect("login.jsp"); %>
(2)編寫login.jsp文件,在該文件中添加用于收集用戶登錄信息的表單及表單元素,關鍵代碼如下:
<form name="form1"method="post"action=""> 用戶名: <input name="name"type="text"id="name"style="width:120px"><br> 密  ;碼: <input name="pwd"type="password"id="pwd"style="width:120px"><br> <br> <input type="submit"name="Submit"value="提交"> </form>
秘笈心法
重定向操作支持將地址重定向到不同的主機上,這一點與轉發不同。在客戶端瀏覽器上將會得到跳轉的地址,并重新發送請求鏈接。用戶可以從瀏覽器的地址欄中看到跳轉后的地址。進行重定向操作后,request中的屬性全部失效,并且開始一個新的request對象。
實例108 防止表單在網站外部提交
光盤位置:光盤\MR\04\108
初級
實用指數:
實例說明
如果靜態網頁中含有用戶提交的表單和字段信息,而從網頁的源代碼中又可以看到網頁被提交的目標地址,那么修改靜態頁面表單提交的目標地址,就可以實現在本地運行靜態網頁并向服務器提交數據的功能。這樣,任何人都可以利用網頁在網站外登錄網站,從而給網站留下嚴重的安全隱患。為解決該問題,本實例介紹一種防止表單在網站外部提交的方法,運行本實例,如圖4.17所示,在“用戶名”文本框中輸入用戶名,在“密碼”文本框中輸入密碼,單擊“提交”按鈕即可進入到網頁的處理頁面,此時地址欄中的地址即為處理頁地址(用戶也可以通過其他方法獲得),當用戶在本地計算機上編寫靜態表單頁時,將目標地址設置為以上地址后,運行網頁并提交表單將顯示如圖4.18所示的提示信息。

圖4.17 表單提交前

圖4.18 從外部提交表單后
關鍵技術
本實例首先使用request.getRequestURL().toString()方法獲得當前網頁的IE地址,然后使用request.getHeader ("referer")請求頁面的地址,接著使用URL urlOne = new URL(String url)的方法分別獲取兩個IE地址服務器主機名,最后比較兩個主機的名稱是否相同。如果網頁的URL為空,比較時將出現路徑有誤的信息。
設計過程
(1)創建index.jsp頁面,添加表單及相關的表單元素,并設置Form表單的相關屬性值,關鍵代碼如下:
<form name="form1"action="doform.jsp"method="post"> <table align="center"> <tr> <td> </td> </tr> <tr> <td>用戶名:</td> <td><input type="text" name="name"></td> </tr> <tr> <td>密 ;碼:</td> <td><input type="password" name="pass"></td> </tr> <tr> <td align="center" colspan="2"> <input type="submit" name="action2" value="提交"> <input type="reset" name="Submit" value="重置"> </td> </tr> </table> </form>
(2)如果表單被提交,將判斷表單提交的路徑是否有誤,如果提交的路徑有誤,系統將給予提示,并禁止從網站外部進行提交表單,關鍵代碼如下:
<% String address=request.getHeader("referer"); //獲取頁面的請求地址 String pathAdd=""; //定義空字符串 if(address! =null){ //判斷當頁面的請求地址為空時 URL urlOne=new URL(address); //實例化URL方法 pathAdd=urlOne.getHost(); //獲取請求頁面的服務器主機 } String address1=request.getRequestURL().toString(); //獲取當前網頁的地址 String pathAdd1 = ""; if (address1 ! = null) { URL urlTwo = new URL(address1); pathAdd1=urlTwo.getHost(); //獲取當前網頁的服務器主機 } %> <body> <table align="center"> <tr><td> </td></tr> <tr> <td> <% if (! pathAdd.equals(pathAdd1)) { //判斷當前頁面的主機與服務器的主機是否相同 %>
秘笈心法
由于網站服務器的名稱是唯一的,而且每次從客戶端瀏覽服務器網頁時,所瀏覽的網頁中包含了網頁的來源信息,因此可以通過比較服務器名稱的方法來防止表單在網站外被提交。
實例109 通過Application對象實現網站計數器
光盤位置:光盤\MR\04\109
初級
實用指數:
實例說明
Application對象是JSP的一個內建對象。當服務器啟動時,該對象會被自動創建,直到服務器關閉該對象才會消失,并且在此期間可以被多個用戶共同使用。這是不同于session對象的。本實例將使用Application對象實現網站計數器,程序運行結果如圖4.19所示。

圖4.19 Application對象實現的網站計數器
關鍵技術
本實例主要使用Application對象的setAttribute()和getAttribute()方法,下面分別進行介紹。
(1)setAttribute()方法
語法格式如下:
setAttribute(String key, String value)
功能:在Application對象中添加屬性。
參數說明
? key:此參數設置屬性名稱。
? value:此參數設置屬性值。
(2)getAttribute()方法
語法格式如下:
getAttribute(String key)
功能:獲取指定屬性的值。
參數說明
key:此參數意義同setAttribute()方法的key參數。
設計過程
創建一個首頁面index.jsp,當用戶訪問該頁面時,程序會自動將網站的訪問次數加1,關鍵代碼如下:
<% int i=0; synchronized(application){ if(application.getAttribute("times")==null){ //服務器啟動后的第一位訪問者 i=1; } else{ i=Integer.parseInt((String)application.getAttribute("times")); i++; //訪問次數加1 } application.setAttribute("times", Integer.toString(i)); //將訪問次數存入Application對象中 } %> <table> <tr bgcolor="lightgrey"> <td align="center">歡迎訪問!</td> </tr> <tr> <td align="center"> 您是第<b><%=i%></b>位訪問本網站的游客! </td> </tr> </table>
秘笈心法
synchronized(Object){…}方法使多用戶同步共享同一個對象。Object表示被共享的對象,{}中包含對該對象進行操作的代碼。當被共享的對象正在被使用時,其他的用戶只能等待,直到上一個用戶對其操作結束。
實例110 記錄用戶IP地址的計數器
光盤位置:光盤\MR\04\110
初級
實用指數:
實例說明
Application對象是JSP的一個內置對象,當服務器啟動時自動創建直到服務器關閉。本實例是用Application對象的setAttribute()和getAttribute()方法來實現網站計數器功能,運行結果如圖4.20所示。

圖4.20 記錄用戶IP地址和時間的計數器
關鍵技術
本實例應用了request對象的getRemoteAddr()方法,其語法格式如下:
getRemoteAddr()
功能:獲得用戶的IP地址,返回一個字符串型值。
設計過程
(1)創建一個對數據庫操作的DB類,關鍵代碼如下:
package com.count.Online; import java.sql.*; public class DB { private Connection con; private Statement stm; private ResultSet rs; private String classname="com.microsoft.jdbc.sqlserver.SQLServerDriver"; private String url="jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=db_database07"; public DB(){} public Connection getCon(){ try{ Class.forName(classname); }catch(ClassNotFoundException e){ e.printStackTrace(); } try{ con=DriverManager.getConnection(url, "sa", ""); }catch(Exception e){ e.printStackTrace(System.err); con=null; } return con; } public Statement getStmed(){ try{ con=getCon(); stm=con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE; ResultSet.CONCUR_READ_ONLY); }catch(Exception e){e.printStackTrace(System.err); } return stm; } public ResultSet search(String sql){ getStmed(); try{ rs=stm.executeQuery(sql); }catch(Exception e){e.printStackTrace(); } return rs; } public int dosql(String sql){ int i=-1; getStmed(); try{ i=stm.executeUpdate(sql); }catch(Exception e){e.printStackTrace(); } return i; } }
(2)創建一個CountOnline類,在該類中調用DB類中的dosql()方法向數據庫中增加記錄,關鍵代碼如下:
package com.count.Online; import java.sql.*; public class CountOnline { private String userip; //用戶IP地址 private String nowdate; //用戶訪問時間 private int times; //網站的訪問次數 private DB db=new DB(); public CountOnline(){} …//省略了屬性的setXXX()和getXXX()方法 public ResultSet adduser(){ ResultSet rs=null; String sql="insert into tb_IPcount values("+this.times+", '"+this.userip+"', '"+this.nowdate+"')"; //生成SQL語句 try{ db.dosql(sql); //執行SQL語句 rs=db.search("select*from tb_IPcount"); //查詢表中的記錄 }catch(Exception e){e.printStackTrace(); } return rs; //返回結果集 } public void dbclose(){ db.closed(); //釋放資源 } }
(3)創建一個供用戶訪問的頁面index.jsp。在該頁面中獲得網站的訪問次數、訪問用戶的IP地址和訪問時間,然后調用CountOnline類中的方法進行操作,關鍵代碼如下:
<%@ page import="java.util.Date,java.text.*,java.sql.*" %> <jsp:useBean id="mycount" class="com.count.Online.CountOnline"/> <jsp:useBean id="mydb" class="com.count.Online.DB"/> <% SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String sql="select MAX(user_order)from tb_IPcount as max"; //查詢最后一次登錄的次數 ResultSet rs=mydb.search(sql); rs.next(); int max=rs.getInt(1); mydb.closed(); mycount.setTimes(max+1); //設置用戶的訪問排名 String ip=request.getRemoteAddr(); mycount.setUserip(ip); //設置用戶IP地址 String nowdate=format.format(new Date()); mycount.setNowdate(nowdate); //設置用戶的訪問時間 rs=mycount.adduser(); //增加該用戶的訪問信息 %> <table> <tr bgcolor="lightgrey"> <td align="center">第N位訪問者</td> <td align="center">訪問者IP地址</td> <td align="center">訪問時間</td> </tr> <% while(rs.next()){ %> <tr> <td align="center"><%=rs.getInt("user_order")%></td> <td align="center"><%=rs.getString("user_ip")%></td> <td align="center"><%=rs.getString("user_time")%></td> </tr> <% } mycount.dbclose(); //關閉數據庫連接 %> <tr> <td align="center" colspan="3"> 您是第<%=max+1%>位訪問者! <br> 您的IP為:<%=ip%> <br> 您訪問的時間為:<%=nowdate%> </td> </tr> </table>
秘笈心法
在使用Application全局變量時需要注意的是,它是被多個用戶共享的,所以當Application對象正在被使用時應避免其他用戶再對其進行操作。
實例111 只對新用戶計數的計數器
光盤位置:光盤\MR\04\111
初級
實用指數:
實例說明
通過本實例可以計算出有多少個IP訪問網站,也可以計算出每個IP地址的訪問次數。運行本實例,程序將記錄用戶的IP地址和訪問次數,運行結果如圖4.21所示。

圖4.21 只對新用戶計數的計數器
關鍵技術
得到用戶IP地址后,首先在數據表中查詢該IP地址,如果存在則更新該IP地址的訪問次數,否則插入一條新的記錄并將訪問次數設為1。
本實例中使用getRemoteAddr()方法獲取用戶的IP地址,其語法格式如下:
request.getRemoteAddr()
功能:獲取用戶的IP地址,返回值為字符型。
其中參數request為JSP的內建對象。
獲取訪問過的人數實際上就是數據表中的記錄總數,這里可以使用ResultSet類的getRow()方法獲得,其語法格式如下:
rs.getRow()
功能:獲取當前記錄的排列行號,返回int類型值。
其中參數rs為ResultSet類對象。
設計過程
(1)創建一個對數據庫操作的DB類,可參見實例110或光盤中的相關代碼。
(2)創建CountOnline類,在該類中調用DB類中的search()和dosql()方法對數據庫進行操作,關鍵代碼如下:
package com.count.Online; import java.sql.*; public class CountOnline { private String userip; private String nowdate; private int times; private DB db=new DB(); public CountOnline(){} …//省略了屬性的setXXX()和getXXX()方法 public ResultSet checkuser(){ String sql="select * from tb_newusercount where user_ip='"+this.userip+"'"; ResultSet rs=null; try{ rs=db.search(sql); if(rs.next()){ //如果訪問者的IP存在于數據表中,則更新訪問次數 this.times=rs.getInt("user_times")+1; sql="update tb_newusercount set user_times="+this.times+" where user_ip='"+this.userip+"'"; db.dosql(sql); }else{ //否則插入新的記錄 this.times=1; sql="insert into tb_newusercount values('"+this.userip+"',1)"; db.dosql(sql); } rs=db.search("select*from tb_newusercount"); //返回所有記錄 }catch(Exception e){e.printStackTrace(); } return rs; } public void dbclose(){ db.closed(); } }
(3)創建首頁index.jsp。在該頁面中獲得訪問用戶的IP地址,然后調用CountOnline類中的方法進行操作,關鍵代碼如下:
<%@ page import="java.sql.*" %> <jsp:useBean id="mycount" class="com.count.Online.CountOnline"/> <% String ip=request.getRemoteAddr(); mycount.setUserip(ip); ResultSet rs=mycount.checkuser(); rs.last(); int num=rs.getRow(); %> <table> <tr bgcolor="lightgrey"> <td align="center">訪問者IP地址</td> <td align="center">訪問次數</td> </tr> <% rs.beforeFirst() while(rs.next()){ %> <tr> <td align="center"><%=rs.getString("user_ip")%></td> <td align="center"><%= rs.getInt("user_times")%></td> </tr> <% } %> <tr> <td align="center" colspan="2"> 您的IP為:<%=ip%> <br> 您的訪問次數為:<%=mycount.getTimes()%>次 <br> 共有 <%=num%> 個新用戶訪問過本頁 </td> </tr> </table> <% mycount.dbclose(); %>
秘笈心法
在使用ResultSet類的getRow()方法獲取總記錄數之前,應使用ResultSet類的last()方法將記錄指針指向最后一條記錄,其語法格式如下:
rs.last()
功能:將記錄指針指向最后一條記錄,返回boolean類型值。
其中參數rs為ResultSet類對象。
ResultSet類能夠使用last()和getRow()方法的前提是,將查詢結果集設為可滾動的。
實例112 統計用戶在某一頁停留的時間
光盤位置:光盤\MR\04\112
初級
實用指數:
實例說明
運行本實例后將會顯示用戶的登錄時間,并且每過10秒刷新一次頁面顯示用戶的停留時間,實例運行結果如圖4.22所示。

圖4.22 統計用戶在頁面的停留時間
關鍵技術
當用戶訪問頁面時記錄用戶的訪問時間,然后求出當前時間與用戶登錄時間的時間差,即為用戶停留時間。將session的有效活動時間設置為稍大于頁面刷新的時間。
本實例使用的函數和方法分別介紹如下。
(1)Date類的構造函數
語法格式如下:
Date time=new Date()
功能:獲取當前時間。
(2)Date類的getTime()方法
語法格式如下:
DateObject.getTime()
功能:獲取從1970年1月1日午夜起的毫秒數,返回long類型的數值。
其中參數DateObject為Date類對象。
(3)Date類的toLocalString()方法
語法格式如下:
DateObject.toLocalString()
功能:將時間格式化為本地時間格式,返回值為字符型。
其中參數DateObject為Date類對象。
(4)JSP內置對象session的setMaxInactiveInterval()方法
語法格式如下:
session.setMaxInactiveInterval(int num)
功能:設置session對象的有效活動時間,該時間以秒為單位。
其中參數num表示設置的秒數。
(5)JSP內置對象session的isNew()方法
語法格式如下:
session.isNew()
功能:判斷當前用戶是否是新用戶,返回boolean類型值。
當用戶刷新網頁時通過此方法得到的值為false。
設計過程
(1)創建StopTime.java類來計算用戶停留的時間,關鍵代碼如下:
package com.count.stoptime; import java.util.*; public class StopTime { private int h=0; private int m=0; private int s=0; public StopTime(){} public void counttime(Date start){ Date end=new Date(); //獲得當前時間 long howmuch=end.getTime()-start.getTime(); //獲得當前時間與登錄時間相差的毫秒數 h=(int)(howmuch/1000/60/60); //計算小時 howmuch=howmuch-h*60*60*1000; m=(int)(howmuch/1000/60); //計算分鐘 howmuch=howmuch-m*60*1000; s=(int)(howmuch/1000); //計算停留的秒數 } …//省略了屬性的getXXX()方法 }
(2)創建首頁面index.jsp,用于顯示用戶的停留時間,主要代碼如下:
<%@ page import="java.util.*" %> <jsp:useBean id="mycounttime" class="com.count.stoptime.StopTime" scope="page"/> <% session.setMaxInactiveInterval(11); //設置session的有效活動時間為11s Date now=new Date(); //獲取當前時間 if(session.isNew()){ //如果是新用戶,記錄用戶登錄時間 session.setAttribute("start", now); } else{ //調用以用戶登錄時間為參數的counttime()方法,計算停留時間 mycounttime.counttime((Date)session.getAttribute("start")); } %> <meta http-equiv="refresh"content="10"> <! --設置刷新時間--> <table> <tr> <td align="center"> 您登錄的時間為:<%=((Date)session.getAttribute("start")).toLocaleString()%> </td> </tr> <tr> <td align="center"> 您在本頁的停留時間為:<%=mycounttime.getH()%>小時<%=mycounttime.getM()%>分 <%=mycounttime.getS()%>秒 </td> </tr> </table>
秘笈心法
設置頁面的刷新時間還可以使用另一種方法—response.setHeader("Refresh","10"),該方法表示10秒刷新一次頁面。
實例113 應用session對象實現用戶登錄
光盤位置:光盤\MR\04\113
初級
實用指數:
實例說明
session在網絡中被稱為會話。由于HTTP協議是一種無狀態協議,也就是當一個客戶向服務器發出請求時,服務器接收請求并返回響應后,該連接結束,而服務器并不保存相關的信息。為了彌補這一缺點,HTTP協議提供了session。通過session可以在應用程序的Web頁間進行跳轉,并保存用戶的狀態,使整個用戶會話一直存在下去,直到關閉瀏覽器。但是,如果在一個會話中,客戶端長時間不向服務器發出請求,session對象就會自動消失。這個時間取決于服務器,例如,Tomcat服務器默認為30分鐘。不過這個時間可以通過編寫程序進行修改。使用session對象一個最常用的功能就是記錄用戶的狀態。下面將通過一個具體的實例介紹應用session對象實現用戶登錄。運行本實例,首先進入的是用戶登錄頁面,輸入用戶名(mr)和密碼(mrsoft)后,單擊“提交”按鈕,將顯示如圖4.23所示的系統主頁,如果輸入用戶名mr,密碼不輸入mrsoft,則重新返回到用戶登錄頁面。在系統主頁,單擊“退出”超鏈接,將銷毀當前session,重新返回到用戶登錄頁面。

圖4.23 系統主頁
關鍵技術
通過session對象可以存儲或讀取客戶相關的信息,如用戶名、購物信息等。這可以通過session對象的setAttribute()方法和getAttribute()方法實現,下面分別進行介紹。
(1)setAttribute()方法
該方法用于將信息保存在session范圍內,語法格式如下:
session.setAttribute(String name, Object obj)
參數說明
? name:用于指定作用域在session范圍內的變量名。
? obj:保存在session范圍內的對象。
例如,將用戶名“無語”保存到session范圍內的username變量中,可以使用下面的代碼:
session.setAttribute("username", "無語");
(2)getAttribute()方法
該方法用于獲取保存在session范圍內的信息,語法格式如下:
getAtttibute(String name)
參數說明
name:指定保存在session范圍內的關鍵字。
例如,讀取保存到session范圍內的username變量的值,可以使用下面的代碼:
session.getAttribute("username");
設計過程
(1)創建index.jsp文件,在該文件中添加用于收集用戶登錄信息的表單及表單元素,關鍵代碼如下:
<form name="form1"method="post"action=""> 用戶名: <input name="name"type="text"id="name"style="width:120px"><br> 密  ;碼: <input name="pwd"type="password"id="pwd"style="width:120px"><br> <br> <input type="submit"name="Submit"value="提交"> </form>
(2)編寫deal.jsp文件,在該文件中模擬用戶登錄(這里將用戶信息保存到一個二維數組中),如果用戶登錄成功,將用戶名保存到session范圍內的變量中,并將頁面重定向到main.jsp頁面;否則,將頁面重定向到index.jsp頁面,重新登錄。deal.jsp文件的具體代碼如下:
<%@page language="java"contentType="text/html;charset=GB18030"pageEncoding="GB18030"%> <%@page import="java.util.*"%> <% String[][]userList={{"mr", "mrsoft"}, {"wgh", "111"}, {"sk", "111"}}; //定義一個保存用戶列表的二維數組 boolean flag=false; //登錄狀態 request.setCharacterEncoding("GB18030"); //設置編碼 String username=request.getParameter("username"); //獲取用戶名 String pwd=request.getParameter("pwd"); //獲取密碼 for(int i=0; i<userList.length; i++){ //遍歷二維數組 if(userList[i][0].equals(username)){ //判斷用戶名 if(userList[i][1].equals(pwd)){ //判斷密碼 flag=true; //表示登錄成功 break; //跳出for循環 } } } if(flag){ //如果值為true,表示登錄成功 session.setAttribute("username", username); //保存用戶名到session范圍的變量中 response.sendRedirect("main.jsp"); //跳轉到主頁 }else{ response.sendRedirect("index.jsp"); //跳轉到用戶登錄頁面 } %>
(3)編寫main.jsp文件,在該文件中,首先獲取并顯示保存到session范圍內的變量,然后添加一個退出超鏈接。main.jsp文件的具體代碼如下:
<%@page language="java"contentType="text/html;charset=GB18030"pageEncoding="GB18030"%> <% String username=(String)session.getAttribute("username"); //獲取保存在session范圍內的用戶名 %> <html> <head> <meta http-equiv="Content-Type"content="text/html;charset=GB18030"> <title>系統主頁</title> </head> <body> 您好![<%=username %>]歡迎您訪問!<br> <a href="exit.jsp">[退出]</a> </body> </html>
(4)編寫exit.jsp文件,在該文件中銷毀session,并重定向頁面到index.jsp頁面。exit.jsp文件的具體代碼如下:
<%@page language="java"contentType="text/html;charset=GB18030"pageEncoding="GB18030"%> <% session.invalidate(); //銷毀session response.sendRedirect("index.jsp"); //重定向頁面到index.jsp %>
秘笈心法
雖然客戶端長時間不向服務器發送請求后,session對象會自動消失,但對于某些實時統計在線人數的網站(如聊天室),每次都等session過期后,才能統計出準確的人數,這是遠遠不夠的。所以還需要手動銷毀session。通過session對象的invalidate()方法可以銷毀session,語法格式如下:
session.invalidate();
session對象被銷毀后,將不可以再使用該session對象。如果在session被銷毀后,再調用session對象的任何方法,都將報出Session already invalidated異常。
實例114 統計用戶在站點停留的時間
光盤位置:光盤\MR\04\114
初級
實用指數:
實例說明
用戶在站點的停留時間可以通過計算從session對象的創建到session對象的銷毀之間的時間差來得到。運行本實例,系統會在用戶下線時把用戶的登錄、離開和停留時間寫進數據表中,如圖4.24所示。

圖4.24 統計用戶在站點停留的時間
關鍵技術
本實例主要繼承HttpSessionBindingListener接口監聽會話的創建與銷毀。繼承該接口的類必須實現繼承的抽象方法valueBound(HttpSessionBindingEvent)和valueUnbound(HttpSessionBindingEvent)。前者在向session中存入實現該接口的類對象時觸發,后者在從session移除該對象時觸發。
設計過程
(1)創建對數據庫進行操作的DB類文件,關鍵代碼如下:
public class DB {
private Connection con;
private Statement stm;
private ResultSet rs;
private String classname="com.microsoft.jdbc.sqlserver.SQLServerDriver";
private String url="jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=db_database08";
public DB(){}
public Connection getCon(){
try{
Class.forName(classname); //加載數據庫驅動類
con=DriverManager.getConnection(url, "sa", ""); //獲取數據庫連接
}catch(Exception e){
e.printStackTrace();
}
return con;
}
public Statement getStm(){
try{
con=getCon(); //獲取數據庫連接
stm=con.createStatement(); //獲取stm對象
}catch(Exception e){e.printStackTrace(System.err); }
return stm; //返回stm對象
}
public int dosql(String sql){ //執行SQL語句
int i=-1;
getStm(); //獲取stm對象
try{
i=stm.executeUpdate(sql); //執行SQL語句,獲取執行結果
}catch(Exception e){e.printStackTrace(); }
return i; //返回執行結果
}
}
(2)創建StopTime類,該類用來計算停留的時間,關鍵代碼如下:
package com.count.stoptime; import java.util.*; import java.text.*; public class StopTime { private int h=0; private int m=0; private int s=0; private Date start=null; //創建時間 private Date end=null; //結束時間 private SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); public StopTime(){} public void setStart(Date start){ this.start=start; } public void counttime(Date end){ //計算停留時間的方法 his.end=end; long howmuch=this.end.getTime()-start.getTime(); //計算出相差的毫秒數 h=(int)(howmuch/1000/60/60); //計算出小時 howmuch=howmuch-h*60*60*1000; //剩余的毫秒數 m=(int)(howmuch/1000/60); //計算出分鐘 howmuch=howmuch-m*60*1000; s=(int)(howmuch/1000); //計算出秒數 } public String getTimes(){ String times=this.h+"小時"+this.m+"分"+this.s+"秒"; return times; } public String getStart(){ return format.format(start); } public String getEnd(){ return format.format(end); } }
(3)創建UserLine類,該類實現HTTP會話的監聽,關鍵代碼如下:
package com.count.stoptime; import java.util.*; import javax.servlet.http.HttpSessionBindingEvent; public class UserLine implements javax.servlet.http.HttpSessionBindingListener{ private String userip; private StopTime stoptime=new StopTime(); public UserLine(){ username=""; } …//省略了屬性的setXXX()和getXXX()方法 public void valueBound(HttpSessionBindingEvent arg0){ stoptime.setStart(new Date()); //記錄創建的時間 System.out.println(this.userip+"于"+new Date().toLocaleString()+"上線!"); } public void valueUnbound(HttpSessionBindingEvent arg0){ stoptime.counttime(new Date()); //計算停留時間 System.out.println(this.userip+"于"+new Date().toLocaleString()+"下線!"); writetime(); //將信息寫入數據庫中 } public void writetime(){ String starttime=stoptime.getStart(); String endtime=stoptime.getEnd(); String times=stoptime.getTimes(); String sql="insert into tb_stoptime values('"+starttime+"', '" +endtime+"', '"+times+"')"; DB db=new DB(); db.dosql(sql); db.closed(); } }
(4)創建站點的首頁面index.jsp。當用戶訪問該頁面時,先設置session的有效活動時間,當將實現會話監聽的類對象存入session對象后,觸發監聽器的valueBound()方法記錄用戶的登錄時間,關鍵代碼如下:
<%@ page import="com.count.stoptime.*" %> <% session.setMaxInactiveInterval(10); //設置session的有效活動時間 String userip=request.getRemoteAddr(); //獲得用戶的IP地址 UserLine userline=new UserLine(); //實例化一個監聽類對象 userline.setUserip(userip); //設置IP session.setAttribute("logonuser", userline); //將實例化的監聽類對象存入session對象中 %> <table> <tr bgcolor="lightgrey" height="25"> <td align="center"> 歡迎登錄! </td> </tr> <tr> <td> 本實例用于統計用戶在站點的停留時間。<br> 該時間是一個session對象從創建到結束期間的時間差。<br> 本實例應用了Servlet事件監聽中對會話監聽的方法。<br> 主要是通過繼承HttpSessionBindingListener接口監聽對HTTP會話操作! </td> </tr> </table>
秘笈心法
HttpSessionBindingListener接口能夠監聽會話與一個屬性綁定或解除綁定的事件,當Web應用把一個屬性與會話綁定后,Servlet容器會調用該接口的valueBound()方法,當Web應用將要把一個屬性與會話解除綁定之前,Servlet容器會調用valueUnbound()方法。
實例115 判斷用戶是否在線
光盤位置:光盤\MR\04\115
初級
實用指數:
實例說明
本實例中判斷用戶是否在線是通過對HTTP會話的監聽來實現的。運行本實例,用戶可以輸入任意用戶名進行登錄,如果用戶名正在使用,則提示“該用戶已在線”,否則進入如圖4.25所示的頁面。

圖4.25 判斷用戶是否在線
關鍵技術
通過繼承HttpSessionBindingListener接口實現對HTTP會話的監聽。繼承該接口的類必須實現繼承的抽象方法valueBound(HttpSessionBindingEvent)和valueUnbound(HttpSessionBinding Event)。前者在向session中存入實現該接口的對象時觸發,后者在從session移除該對象時觸發。
設計過程
(1)創建監聽HTTP會話的OnLine類文件,具體代碼如下:
package com.line; import java.util.*; import javax.servlet.*; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; public class OnLine implements HttpSessionBindingListener{ private String username; //用戶輸入的用戶名 private boolean mark=true; private Vector vc=new Vector(); public void setUsername(String username){ this.username=username; } public void valueBound(HttpSessionBindingEvent se) { HttpSession session=se.getSession(); ServletContext sct=session.getServletContext(); //該對象可被所有頁面共享 vc=(Vector)sct.getAttribute("online"); if(vc==null){ //服務器啟動后,第一個用戶進行訪問 vc=new Vector(); vc.add(username); }else{ if(vc.contains(username)){ //如果存在該用戶 mark=false; }else vc.add(username); } sct.setAttribute("online", vc); } public void valueUnbound(HttpSessionBindingEvent se) { HttpSession session=se.getSession(); ServletContext sct=session.getServletContext(); vc=(Vector)sct.getAttribute("online"); if(vc! =null){ vc.removeElement(this.username); //用戶下線時移除該用戶 } } public boolean getMark(){ return this.mark; } }
(2)創建UserLogOn類文件,其中的checkuser()方法用來驗證用戶信息并返回一個boolean類型值。該類在用戶名不為空的情況下,調用OnLine類中的方法進行相應的操作,關鍵代碼如下:
package com.line; import javax.servlet.http.HttpSession; public class UserLogOn { private String username; private String backstr=""; private OnLine on=new OnLine(); public UserLogOn(){} …//省略了username屬性的setXXX()和getXXX()方法 public boolean checkuser(HttpSession session){ boolean mark=true; if(this.username==null||this.username.equals("")){ this.backstr="<li>請輸入<b>用戶名!</b></li><br>"; mark=false; } if(mark){ on.setUsername(this.username); session.setAttribute("onlineuser", on); //將OnLine監聽類對象存入session中 mark=on.getMark(); if(! mark) this.backstr="該用戶已在線!"; } return mark; } public String getBackstr(){ return this.backstr; } }
(3)創建首頁面index.jsp供用戶輸入登錄信息,關鍵代碼如下:
<form action="dologon.jsp"> <table> <tr bgcolor="lightgrey" height="30"> <td align="center">用戶登錄</td> </tr> <tr height="30"> <td align="center"> 用戶名:<input type="text" name="username" size="30"> </td> </tr> <tr bgcolor="lightgrey"> <td align="center"> <input type="submit" name="logon" value="登錄"> <input type="reset" name="clear" value="重置"> </td> </tr> </table> </form>
(4)創建接收Form表單的頁面dologon.jsp。在該頁面中調用UserLogOn類中的checkuser()方法來驗證用戶身份。如果輸入的用戶名不為空并且該用戶不在線,則轉向myline.jsp頁面,關鍵代碼如下:
<jsp:useBean id="mylogon" class="com.line.UserLogOn"/> <% String username=request.getParameter("username"); if(username==null) username=""; username=new String(username.getBytes("ISO-8859-1"), "gbk"); mylogon.setUsername(username); //設置用戶名 if(mylogon.checkuser(session)){ //如果用戶名不為空并且該用戶不在線 session.setAttribute("username", username); response.sendRedirect("myline.jsp"); } %> <table> <tr bgcolor="lightgrey" height="30"> <td align="center">登錄狀況</td> </tr> <tr height="50"> <td align="center"> <%=mylogon.getBackstr()%> </td> </tr> </table>
(5)創建myline.jsp頁面,該頁面用于顯示用戶的在線情況,關鍵代碼如下:
<%@ page import="java.util.*"%> <% session.setMaxInactiveInterval(10); Vector vec=(Vector)application.getAttribute("online"); %> …… <meta http-equiv="refresh" content="12"> …… <table> <tr> <td width="60%" align="center" valign="middle">10秒內沒有發言<br>您將被視為下線</td> </tr> <tr> <td align="center" valign="middle"> <% if(vec==null||vec.size()==0) out.println("沒有用戶!"); else{ if(vec.contains(session.getAttribute("username"))){ out.println("您已經上線!用戶名:"+session.getAttribute("username")); } else out.println("您沒有上線!"); } %> </td> </tr> <tr bgcolor="lightgrey"> <td align="center" height="25" colspan="2"> <% if(session.getAttribute("username")==null) //表示session過期已銷毀 out.println("您已經下線!"); else if(vec.contains(session.getAttribute("username"))) out.println("<a href='myline.jsp'>[發言]</a>"); else out.println("請先登錄!"); %> </table> <% if(! vec.contains(session.getAttribute("username"))) out.println("<a href='index.jsp'>[登錄]</a>"); %>
秘笈心法
本實例另外設置一個Vector對象,并將它存入Application對象中,以用來存儲在線的用戶。當用戶登錄時,如果用戶名存在于Vector對象中,則提示“該用戶已在線”信息,否則將該用戶名存入Vector對象中;當用戶下線時,從Vector對象中移除該用戶名。
實例116 實時統計在線人數
光盤位置:光盤\MR\04\116
初級
實用指數:
實例說明
本實例主要實現顯示正在訪問網站人數的功能,它可以使管理員知道網站當前被訪問的情況,以此來了解網站的受關注程度。運行本實例,頁面中將顯示正在訪問網站的所有用戶,并統計出在線人數,實例運行效果如圖4.26所示。

圖4.26 實時統計在線人數
關鍵技術
本實例應用的方法介紹如下。
(1)Vector對象的elements()方法
語法格式如下:
Enumeration em=VectorObject.elements()
功能:返回Vector對象中的所有值,其結果是一個Enumeration枚舉對象。
參數說明
? em:表示一個Enumeration枚舉對象。
? VectorObject:表示實例化的Vector對象。
(2)EnumerationObject對象的nextElement()方法
語法格式如下:
EnumerationObject.nextElement()
功能:遍歷枚舉對象中的值。使用該方法獲得的值應強制轉換為該值原來的類型。
(3)Enumeration枚舉對象的hasMoreElements()方法
語法格式如下:
EnumerationObject.hasMoreElements()
功能:判斷枚舉對象中是否還存在值,該方法返回一個boolean類型值。
其中參數EnumerationObject為實例化的枚舉對象。
設計過程
(1)創建用于監聽HTTP會話的OnLine類文件和用于驗證登錄信息的LogOnNum類文件。由于這兩個類的實現技術與實例115中的OnLine類和User LogOn類相同,在此不再贅述。
(2)創建一個首頁面index.jsp供用戶輸入登錄信息。相關代碼可參見實例115。
(3)創建接收Form表單的頁面dologon.jsp。相關代碼可參見實例115中的dologon.jsp文件或光盤。
(4)創建online.jsp頁面,該頁面用于顯示所有在線用戶的信息,關鍵代碼如下:
<%@ page import="java.util.*"%> <% session.setMaxInactiveInterval(10); Vector vec=(Vector)application.getAttribute("online"); %> <table> <tr> <td align="left" valign="middle"> <table> <% if(vec==null||vec.size()==0) out.println("<tr><td align='center'>沒有用戶!</td></tr>"); else{ //顯示所有在線用戶 Enumeration em=vec.elements(); while(em.hasMoreElements()){ String username=(String)em.nextElement(); if(username.equals(session.getAttribute("username"))) out.println("<tr><td align='left'><li><font color='red'>"+username+"</font></td></tr>"); else out.println("<tr><td align='left'><li>"+username+"</td></tr>"); }//while } %> </table> </td> </tr> <tr bgcolor="lightgrey"> <td align="center" height="25" colspan="2"> <% if(session.getAttribute("username")==null){ out.println("您已經下線!"); } else{ if(vec.contains(session.getAttribute("username"))){ out.println("<a href='online.jsp'>[發言]</a>"); out.println("在線人數 "+vec.size()+" 人!"); } else out.println("請先登錄!"); } %> </table> <% if(! vec.contains(session.getAttribute("username"))) out.println("<a href='index.jsp'>[登錄]</a>"); %>
秘笈心法
本實例主要是通過HttpSessionBindingListener接口來監聽session會話的綁定狀態,當用戶登錄時,會將用戶名保存到session中,這時就會觸發HttpSessionBindingListener接口的valueBound()方法,然后將用戶名保存在Vector中,再將Vector存儲在ServletContext中,最后在頁面中讀取出用戶名信息并顯示,此時設置session的有效期為10秒,當session超時后,就會觸發HttpSessionBindingListener接口的valueUnBound()方法,然后從Vector中移出當前的用戶。