關於Servlet會話跟蹤的那些事兒


  關於servlet會話跟蹤,一搜都能搜出很多。我也不免落入俗套,也總結了一把。希望我所總結的知識盡量是知識海洋里的一汪清泉。能幫助到我自己和哪怕一個人,那也是值得的。

故事由來:

  我們知道,http協議是個無狀態的協議,所謂無狀態就是指此時刻我們的狀態是保持連接,下一刻我們的狀態可能就是斷開連接,狀態是不穩定的,這就導致很多用戶在上網時遇到問題,比如購物,我添加幾次商品到購物車,如果沒有會話跟蹤,那么這些商品是沒辦法添加到一個購物車中的。再比如登錄,每次訪問同一個網站時,我每次都要輸入用戶名和密碼,在同一個網站中,每個界面都要輸入一次用戶名和密碼才能繼續做其他事情。這就很尷尬了,所以,有會話跟蹤技術的機制就誕生了。

故事梗概:

維持會話技術的4大法寶

  法寶1:Cookie 

  cookie在瀏覽器允許使用的狀態下,當客戶請求服務器后,服務器會發送一個含有唯一的sessionID的cookie給客戶端,並保存到客戶端本地,下次客戶端再和服務器交互時,通過在request頭中加入cookie中的信息,服務器能辨識出客戶身份,從而維持會話。

  法寶2:隱藏的表單字段

  在<input>中添加一個隱藏的字段,比如這樣:

  <input type="hidden" name="sessionid" value="12345"> 

那么在提交表單時,會把這個隱藏的名為sessionID的值為12345的域提交在GET或者POST數據中,服務器收到我的請求后,會給一個客戶端一個cookie中有

Cookie:JSESSIONID=E6047C8DB41EEA107256ECB443640C49

每次向服務器請求時,就帶着我的JSESSIONID,服務器會認識我的JSESSIONID給我發送我需要的請求。

  法寶3:URL重寫

  在每個 URL 末尾追加一些額外的數據來標識 session 會話,服務器會把該 session 會話標識符與已存儲的有關 session 會話的數據相關聯。session 會話標識符被附加為 sessionid=12345,標識符可被 Web 服務器訪問以識別客戶端。

  介紹完上面3個,下面是隆重登場的主角了。

  法寶4:使用HttpSession

  每一個事物產生都有它的作用,session也是,session由servlet容器產生,是一種會話跟蹤技術,能解決用戶在登錄或者購物時多頁面請求或存儲相關用戶信息。

  比如這么個場景:你在打開淘寶,然后看到個想買的商品后,你點擊立即購買,但是這時候會跳到登錄那個新的界面,然后你登錄之后,什么事都不用做,再次回到那個商品購買界面刷新下,你就發現這時候你再買這個商品就可以了。這就是session的作用。
  多說一句:上面說到的cookie,其中就包含有session的ID,session是借助cookie來實現會話跟蹤的,所以,如果cookie被刪或者禁用的話,session這個會話跟蹤技術也就無法使用了。

  

故事真相:

session的前世今生:

這是后來補的,因為之前對session的理解有偏差,所以這里糾正下。由問答形式給出。

session由誰創建,怎么創建?
session由服務器端創建,創建方式:HttpSession session = request.getSession(true)。
session在哪保存?
session保存在服務器端,session創建好會由Tomcat的StandardManager類將session存儲在服務器內存中,也可以持久化到DB,file,redis中。
session既然由服務器創建,那么在Tomcat中如何創建的?
在tomcat服務器中由ManagerBase類提供創建方法:隨機數+時間+jvmid。
session有哪些接口?
創建好session后就可以使用session的API了,API在下面給出。
客戶端會保存session嗎?
客戶端(瀏覽器端)是不會保存session的,session在服務器端保存,客戶端只保存一個sessionid到cookie中,而不會保存session。
session最終是怎么銷毀的?
通過session.invalidate、超時、關閉服務器中三者之一。單純關閉瀏覽器session不會消失,因為session不在瀏覽器端保存,而在服務器端。

 

session的API如下:

public Object getAttribute(String name)

該方法返回在該 session 會話中具有指定名稱的對象,如果沒有指定名稱的對象,則返回 null。

public Enumeration getAttributeNames()

該方法返回 String 對象的枚舉,String 對象包含所有綁定到該 session 會話的對象的名稱。

public long getCreationTime()

該方法返回該 session 會話被創建的時間,自格林尼治標准時間 1970 年 1 月 1 日午夜算起,以毫秒為單位。

public String getId()

該方法返回一個包含分配給該 session 會話的唯一標識符的字符串。

public long getLastAccessedTime()

該方法返回客戶端最后一次發送與該 session 會話相關的請求的時間自格林尼治標准時間 1970 年 1 月 1 日午夜算起,以毫秒為單位。

public int getMaxInactiveInterval()

該方法返回 Servlet 容器在客戶端訪問時保持 session 會話打開的最大時間間隔,以秒為單位。

public void invalidate()

該方法指示該 session 會話無效,並解除綁定到它上面的任何對象。

public boolean isNew()

如果客戶端還不知道該 session 會話,或者如果客戶選擇不參入該 session 會話,則該方法返回 true。

public void removeAttribute(String name)

該方法將從該 session 會話移除指定名稱的對象。

public void setAttribute(String name, Object value) 

該方法使用指定的名稱綁定一個對象到該 session 會話。

public void setMaxInactiveInterval(int interval)

該方法在 Servlet 容器指示該 session 會話無效之前,指定客戶端請求之間的時間,以秒為單位。

 

下面說的是session和session的ID,不同的訪問者對不同的session和sessionID,

舉例如下,一個test.html,一個testSession.java,一個google chrome,一個火狐瀏覽器。

test.html文件如下:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta charset="UTF-8">
 5 <title>Test</title>
 6 </head>
 7 <body>
 8     <form action="http://127.0.0.1:8081/HelloServlet/testSession" method="post">
 9         <input type="text" name="username" />
10         <input type="submit" />
11     </form>
12 </body>
13 </html>

testSession.java文件如下(.java文件使用的是eclipse下創建的servlet文件)

  1 package com.hundsun.vivizhang.servlet;
  2 
  3 import java.io.IOException;
  4 
  5 import java.io.PrintWriter;
  6 import java.util.Date;
  7 
  8 import javax.jws.WebService;
  9 import javax.servlet.ServletException;
 10 import javax.servlet.annotation.WebServlet;
 11 import javax.servlet.http.HttpServlet;
 12 import javax.servlet.http.HttpServletRequest;
 13 import javax.servlet.http.HttpServletResponse;
 14 import javax.servlet.http.HttpSession;
 15 
 16 @WebServlet("/testSession")
 17 public class testSession extends HttpServlet{
 18     private static final long serialVersionUID = 1L;
 19 
 20     /**
 21      * @see HttpServlet#HttpServlet()
 22      */
 23     public testSession() {
 24         super();
 25         // TODO Auto-generated constructor stub
 26     }
 27 
 28     /**
 29      * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
 30      *      response)
 31      */
 32     protected void doGet(HttpServletRequest request, HttpServletResponse response)
 33             throws ServletException, IOException {
 34           // Create a session object if it is already not  created.
 35           HttpSession session = request.getSession(true);
 36           // Get session creation time.
 37           Date createTime = new Date(session.getCreationTime());
 38           // Get last access time of this web page.
 39           Date lastAccessTime = 
 40                             new Date(session.getLastAccessedTime());
 41 
 42           String title = "Welcome Back to my website";
 43           Integer visitCount = new Integer(0);
 44           String visitCountKey = new String("visitCount");
 45           String userIDKey = new String("userID");
 46           String userID = new String("ABCD");
 47 
 48           // Check if this is new comer on your web page.
 49           if (session.isNew()){
 50              title = "Welcome to my website";
 51              session.setAttribute(userIDKey, userID);
 52           } else {
 53              visitCount = (Integer)session.getAttribute(visitCountKey);
 54              visitCount = visitCount + 1;
 55              userID = (String)session.getAttribute(userIDKey);
 56           }
 57           session.setAttribute(visitCountKey,  visitCount);
 58 
 59           // Set response content type
 60           response.setContentType("text/html");
 61           PrintWriter out = response.getWriter();
 62 
 63           String docType =
 64           "<!doctype html public \"-//w3c//dtd html 4.0 " +
 65           "transitional//en\">\n";
 66           out.println(docType +
 67                     "<html>\n" +
 68                     "<head><title>" + title + "</title></head>\n" +
 69                     "<body bgcolor=\"#f0f0f0\">\n" +
 70                     "<h1 align=\"center\">" + title + "</h1>\n" +
 71                      "<h2 align=\"center\">Session Infomation</h2>\n" +
 72                     "<table border=\"1\" align=\"center\">\n" +
 73                     "<tr bgcolor=\"#949494\">\n" +
 74                     "  <th>Session info</th><th>value</th></tr>\n" +
 75                     "<tr>\n" +
 76                     "  <td>id</td>\n" +
 77                     "  <td>" + session.getId() + "</td></tr>\n" +
 78                     "<tr>\n" +
 79                     "  <td>Creation Time</td>\n" +
 80                     "  <td>" + createTime + 
 81                     "  </td></tr>\n" +
 82                     "<tr>\n" +
 83                     "  <td>Time of Last Access</td>\n" +
 84                     "  <td>" + lastAccessTime + 
 85                     "  </td></tr>\n" +
 86                     "<tr>\n" +
 87                     "  <td>User ID</td>\n" +
 88                     "  <td>" + userID + 
 89                     "  </td></tr>\n" +
 90                     "<tr>\n" +
 91                     "  <td>Number of visits</td>\n" +
 92                     "  <td>" + visitCount + "</td></tr>\n" +
 93                     "</table>\n" +
 94                     "</body></html>");
 95     }
 96 
 97     /**
 98      * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
 99      *      response)
100      */
101     protected void doPost(HttpServletRequest request, HttpServletResponse response)
102             throws ServletException, IOException {
103         // TODO Auto-generated method stub
104         doGet(request, response);
105     }
106 }

此處不用配置web.xml文件。

實驗開始,先清掉瀏覽器的緩存,然后在瀏覽器中輸入 localhost:8080/HelloServlet/test.html ,我的圖中用的是127.0.0.1的環路地址,是一樣的哈。

輸入完后,打開chrome的F12按鍵,敲擊回車,訪問到頁面,得到的不含cookie的F12中的截圖(圖1)是這樣的。

圖1

然后輸入一些信息,點擊提交后,F12調試頁面是這樣的(圖2)。

圖2

點擊提交后跳轉到這個界面(圖3)

圖3

然后就能得到下面的結論:

(1)同一瀏覽器相同窗口刷新后,訪問的是同一sessionID,如圖4所示,刷新1次,顯示訪問次數為2.

(2)同一瀏覽器不同窗口訪問,訪問的是同一sessionID,如圖4所示,開兩個窗口,但是sessionId仍然是E04B...065.

圖4

(3)同一瀏覽器關閉后再次訪問也不是同一session,如圖5所示,切換到firefox后id和visitCount都不同了。

圖5

(4)不同的瀏覽器訪問是不同session和sessionID。如圖6所示

圖6

故事總結:

  這個故事說的是會話跟蹤的技術,以后在使用Servlet時,要學會使用,這是一個非常重要的技術,但是也聽到有反對使用cookie的,這些都不是重點,重點是這個技術是現在web開發必不可少的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM