官术网_书友最值得收藏!

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>
        密&nbsp; &nbsp;碼: <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>&nbsp; </td>
                  </tr>
                  <tr>
                      <td>用戶名:</td>
                      <td><input type="text" name="name"></td>
                  </tr>
                  <tr>
                      <td>密&nbsp;碼:</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>&nbsp; &nbsp; </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>
        密&nbsp; &nbsp;碼: <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中移出當前的用戶。

主站蜘蛛池模板: 永嘉县| 天长市| 兰溪市| 祥云县| 林州市| 西吉县| 淮阳县| 玉田县| 永兴县| 白沙| 长武县| 克山县| 丰城市| 习水县| 卢湾区| 崇左市| 台东县| 衡南县| 深水埗区| 嘉定区| 桐城市| 东至县| 青龙| 陇西县| 吴堡县| 兴仁县| 福泉市| 永顺县| 夏津县| 英德市| 大悟县| 临汾市| 陵水| 钦州市| 辽阳市| 诏安县| 蒲城县| 巴里| 阿拉善盟| 原平市| 湄潭县|