Servlet - 会话跟踪

  • 简述

    HTTP 是一种“无状态”协议,这意味着每次客户端检索网页时,客户端都会打开与 Web 服务器的单独连接,并且服务器不会自动保留之前客户端请求的任何记录。
    仍然有以下三种方式来维护 Web 客户端和 Web 服务器之间的会话 -
  • cookie

    Web 服务器可以为每个 Web 客户端分配一个唯一的会话 ID 作为 cookie,并且对于来自客户端的后续请求,它们可以使用收到的 cookie 进行识别。
    这可能不是一种有效的方法,因为很多时候浏览器不支持 cookie,所以我不建议使用这个程序来维护会话。
  • 隐藏表单域

    Web 服务器可以发送隐藏的 HTML 表单字段以及唯一的会话 ID,如下所示 -
    
    <input type = "hidden" name = "sessionid" value = "12345">
    
    此条目意味着,在提交表单时,指定的名称和值将自动包含在 GET 或 POST 数据中。每次网页浏览器发回请求时,都可以使用 session_id 值来跟踪不同的网页浏览器。
    这可能是跟踪会话的有效方式,但单击常规 (<A HREF...>) 超文本链接不会导致提交表单,因此隐藏的表单字段也无法支持常规会话跟踪。
  • URL重写

    您可以在标识会话的每个 URL 的末尾附加一些额外的数据,服务器可以将该会话标识符与它存储的有关该会话的数据相关联。
    例如,对于 http://jc2182.com/file.htm;sessionid = 12345,会话标识符附加为 sessionid = 12345,可以在 Web 服务器上访问以识别客户端。
    URL 重写是维护会话的更好方法,即使浏览器不支持 cookie 也能正常工作。URL 重写的缺点是您必须动态生成每个 URL 以分配会话 ID,即使是简单的静态 HTML 页面也是如此。
  • HttpSession 对象

    除了上面提到的三种方式之外,servlet 还提供了 HttpSession 接口,它提供了一种跨多个页面请求或访问网站的方式来识别用户并存储有关该用户的信息。
    servlet 容器使用此接口在 HTTP 客户端和 HTTP 服务器之间创建会话。会话持续指定的时间段,跨越来自用户的多个连接或页面请求。
    您将通过调用公共方法获得 HttpSession 对象 getSession() HttpServletRequest,如下 -
    
    HttpSession session = request.getSession();
    
    在向客户端发送任何文档内容之前,您需要调用request.getSession()。以下是通过 HttpSession 对象可用的重要方法的摘要 -
    序号 方法和说明
    1
    public Object getAttribute(String name)
    此方法返回此会话中与指定名称绑定的对象,如果该名称下未绑定任何对象,则返回 null。
    2
    public Enumeration getAttributeNames()
    此方法返回一个字符串对象枚举,其中包含绑定到此会话的所有对象的名称。
    3
    public long getCreationTime()
    此方法返回创建此会话的时间,以格林威治标准时间 1970 年 1 月 1 日午夜以来的毫秒数为单位。
    4
    public String getId()
    此方法返回一个字符串,其中包含分配给此会话的唯一标识符。
    5
    public long getLastAccessedTime()
    此方法返回会话的最后访问时间,格式为自格林威治标准时间 1970 年 1 月 1 日午夜以来的毫秒数
    6
    public int getMaxInactiveInterval()
    此方法返回最大时间间隔(秒),servlet 容器将在客户端访问之间保持会话打开。
    7
    public void invalidate()
    此方法使此会话无效并解除绑定到它的任何对象。
    8
    public boolean isNew(
    如果客户端还不知道会话或者客户端选择不加入会话,则此方法返回 true。
    9
    public void removeAttribute(String name)
    此方法从此会话中删除与指定名称绑定的对象。
    10
    public void setAttribute(String name, Object value)
    此方法使用指定的名称将对象绑定到此会话。
    11
    public void setMaxInactiveInterval(int interval)
    此方法指定 servlet 容器使此会话无效之前客户端请求之间的时间(以秒为单位)。
  • 会话跟踪示例

    此示例描述如何使用 HttpSession 对象找出会话的创建时间和上次访问时间。如果一个新会话不存在,我们会将一个新会话与该请求相关联。
    
    // Import required java libraries
    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.util.*;
     
    // Extend HttpServlet class
    public class SessionTrack extends HttpServlet {
     
       public void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
             
          // Create a session object if it is already not  created.
          HttpSession session = request.getSession(true);
             
          // Get session creation time.
          Date createTime = new Date(session.getCreationTime());
             
          // Get last access time of this web page.
          Date lastAccessTime = new Date(session.getLastAccessedTime());
          String title = "Welcome Back to my website";
          Integer visitCount = new Integer(0);
          String visitCountKey = new String("visitCount");
          String userIDKey = new String("userID");
          String userID = new String("ABCD");
          // Check if this is new comer on your web page.
          if (session.isNew()) {
             title = "Welcome to my website";
             session.setAttribute(userIDKey, userID);
          } else {
             visitCount = (Integer)session.getAttribute(visitCountKey);
             visitCount = visitCount + 1;
             userID = (String)session.getAttribute(userIDKey);
          }
          session.setAttribute(visitCountKey,  visitCount);
          // Set response content type
          response.setContentType("text/html");
          PrintWriter out = response.getWriter();
          String docType =
             "<!doctype html public \"-//w3c//dtd html 4.0 " +
             "transitional//en\">\n";
          out.println(docType +
             "<html>\n" +
                "<head><title>" + title + "</title></head>\n" +
                
                "<body bgcolor = \"#f0f0f0\">\n" +
                   "<h1 align = \"center\">" + title + "</h1>\n" +
                   "<h2 align = \"center\">Session Infomation</h2>\n" +
                   "<table border = \"1\" align = \"center\">\n" +
                      
                      "<tr bgcolor = \"#949494\">\n" +
                         "  <th>Session info</th><th>value</th>
                      </tr>\n" +
                         
                      "<tr>\n" +
                         "  <td>id</td>\n" +
                         "  <td>" + session.getId() + "</td>
                      </tr>\n" +
                      
                      "<tr>\n" +
                         "  <td>Creation Time</td>\n" +
                         "  <td>" + createTime + "  </td>
                      </tr>\n" +
                      
                      "<tr>\n" +
                         "  <td>Time of Last Access</td>\n" +
                         "  <td>" + lastAccessTime + "  </td>
                      </tr>\n" +
                      
                      "<tr>\n" +
                         "  <td>User ID</td>\n" +
                         "  <td>" + userID + "  </td>
                      </tr>\n" +
                      
                      "<tr>\n" +
                         "  <td>Number of visits</td>\n" +
                         "  <td>" + visitCount + "</td>
                      </tr>\n" +
                   "</table>\n" +
                "</body>
             </html>"
          );
       }
    }
    
    编译上面的servlet SessionTrack并在 web.xml 文件中创建适当的条目。现在运行http://localhost:8080/SessionTrack将在您第一次运行时显示以下结果 -

    Session Infomation

    Session info value
    id 0AE3EC93FF44E3C525B4351B77ABB2D5
    Creation Time Tue Jun 08 17:26:40 GMT+04:00 2010
    Time of Last Access Tue Jun 08 17:26:40 GMT+04:00 2010
    User ID ABCD
    Number of visits 0
    现在尝试第二次运行相同的 servlet,它会显示以下结果。

    Session Infomation

    info type value
    id 0AE3EC93FF44E3C525B4351B77ABB2D5
    Creation Time Tue Jun 08 17:26:40 GMT+04:00 2010
    Time of Last Access Tue Jun 08 17:26:40 GMT+04:00 2010
    User ID ABCD
    Number of visits 1
  • 删除会话数据

    当您完成用户的会话数据时,您有几个选项 -
    • Remove a particular attribute- 您可以调用public void removeAttribute(String name)方法删除与特定键关联的值。
    • Delete the whole session- 您可以调用public void invalidate()方法来丢弃整个会话。
    • Setting Session timeout- 您可以调用public void setMaxInactiveInterval(int interval)方法来单独设置会话的超时时间。
    • Log the user out − 支持servlets 2.4的服务器,可以调用 logout 将客户端从 Web 服务器注销并使属于所有用户的所有会话无效。
    • web.xml Configuration − 如果您使用的是Tomcat,除了上述方法外,您还可以在web.xml 文件中配置会话超时,如下所示。
    
    <session-config>
       <session-timeout>15</session-timeout>
    </session-config>
    
    超时以分钟表示,并覆盖 Tomcat 中的默认超时 30 分钟。
    servlet 中的 getMaxInactiveInterval( ) 方法以秒为单位返回该会话的超时时间。因此,如果您的会话在 web.xml 中配置为 15 分钟,则 getMaxInactiveInterval() 返回 900。