当前位置: 首页 > news >正文

Servlet的会话(Session)跟踪

以下内容引用自http://wiki.jikexueyuan.com/project/servlet/session-tracking.html:

HTTP是一种“无状态”协议,这意味着每次客户端检索Web页面时,客户端打开一个单独的连接到Web服务器,服务器不会自动保存之前客户端请求的任何记录。

仍然有以下三种方式来维持Web客户端和Web服务器之间的会话:

一、Cookies

一个Web服务器可以分配一个唯一的会话ID作为每个Web客户端的Cookie,并且对于来自客户端的后续请求,它们可以使用已接收的Cookie来识别。

这可能不是一个有效的方法,因为很多时候浏览器不支持Cookie,所以我不建议使用这种方式来维持会话(由于年代问题,现在的浏览器全部都支持Cookie)。

二、隐藏的表单字段

一个Web服务器可以发送一个隐藏的HTML表单字段以及一个唯一的会话ID,如下所示:

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

该条目意味着,当表单被提交时,指定的名称和值会被自动包含在GET或POST数据中。每次当Web浏览器发送回请求时,session_id的值可以用于跟踪不同的Web浏览器。

这可能是保持会话跟踪的一种有效的方式,但是点击常规的(<A HREF...>)超文本链接不会导致表单提交,因此隐藏的表单字段也不支持常规的会话跟踪。

三、URL重写

可以在每个标识会话的URL末尾追加一些额外的数据,且服务器会把该会话标识符与它已存储的有关会话的数据关联起来。

例如,http://jsoft.com/file.htm;sessionid=12345,会话标识符被附加为sessionid=12345,可能会在Web服务器端被访问来识别客户端。

URL重写是维持会话的一种更好的方式,当浏览器不支持Cookie时为浏览器工作,但是它的缺点是会动态的生成每个URL来分配会话ID,即使页面是简单的静态的HTML页面。

四、HttpSession对象

除了上述提到的三种方式,Servlet还提供了HttpSession接口,该接口提供了一种对网站的跨多个页面请求或访问的方法来识别用户并存储有关用户的信息。

Servlet容器使用这个接口来创建在HTTP客户端和HTTP服务器之间的会话。会话在一个指定的时间段内持续,跨多个连接或来自用户的请求。

可以通过调用HttpServletRequest的公共方法getSession()来获取HttpSession对象,如下所示:

HttpSession session = request.getSession();

在向客户端发送任何文档内容之前,需要调用request.getSession()。这里是一些重要方法的总结,这些方法通过HttpSession对象是可用的:

方法描述

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会话无效之前,指定客户端请求之间的时间,以秒为单位。

五、会话跟踪实例

这个例子描述了如何使用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>");
  }
}

配置web.xml:

    <servlet>
        <servlet-name>SessionTrack</servlet-name>
        <servlet-class>com.jsoft.testservletbasics.SessionTrack</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SessionTrack</servlet-name>
        <url-pattern>/SessionTrack</url-pattern>
    </servlet-mapping>

编译上述Servlet SessionTrack并在web.xml文件中创建适当的条目。在浏览器地址栏输入http://localhost:8080/SessionTrack,当第一次运行时将显示如下所示的结果:

现在尝试再次运行相同的Servlet,它将显示如下所示的结果:

六、删除会话数据

当完成了一个用户的会话数据,有以下几种选择:

  • 移除一个特定的属性:可以调用public void removeAttribute(String name)方法来删除与特定的键相关联的值。

  • 删除整个会话:可以调用public void invalidate()方法来删除整个会话。

  • 设置会话超时:可以调用public void setMaxInactiveInterval(int interval)方法来单独设置会话超时。

  • 注销用户:支持Servlet 2.4的服务器,可以调用logout来注销Web服务器的客户端,并把属于所有用户的所有会话设置为无效。

  • web.xml配置:如果使用的是Tomcat,除了上述方法,还可以在web.xml文件中配置会话超时,如下所示:
<session-config>
    <session-timeout>15</session-timeout>
</session-config>

超时时间是以分钟为单位的,并覆盖了Tomcat中默认的30分钟的超时时间。

Servlet中的getMaxInactiveInterval()方法为会话返回的超时时间是以秒为单位的。所以如果在web.xml中配置会话超时时间为15分钟,那么getMaxInactiveInterval()会返回900。

 

测试工程:https://github.com/easonjim/5_java_example/tree/master/servletbasics/test9

转载于:https://www.cnblogs.com/EasonJim/p/6976163.html

相关文章:

  • VSCode
  • 软件工程--团队答辩
  • MVC中一般为什么用IQueryable而不是用IList
  • win7 Pthreads
  • Java -- Java 类集 -- 目录
  • Linux IPC实践(4) --System V消息队列(1)
  • CSS的子选择器与后代选择器的区别
  • salt Rosters
  • 14_通过sharedPreferences保存用户名密码
  • codeforces 814D (DFS)
  • [转]eclipse 配置黑色主题 Luna 方式三
  • bootstrap validate remote 自定义message返回
  • e课表项目第二次冲刺周期第十天
  • http 又想起了苑
  • 使用JPA和Hibernate进行批量处理的最佳方式
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • java中的hashCode
  • LeetCode算法系列_0891_子序列宽度之和
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • python docx文档转html页面
  • Spark RDD学习: aggregate函数
  • ViewService——一种保证客户端与服务端同步的方法
  • vue的全局变量和全局拦截请求器
  • XML已死 ?
  • 构造函数(constructor)与原型链(prototype)关系
  • 力扣(LeetCode)21
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • 自定义函数
  • 阿里云移动端播放器高级功能介绍
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • # Apache SeaTunnel 究竟是什么?
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #QT项目实战(天气预报)
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (待修改)PyG安装步骤
  • (二)WCF的Binding模型
  • (接口封装)
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转)iOS字体
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .bat文件调用java类的main方法
  • .gitignore文件—git忽略文件
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .NET性能优化(文摘)
  • .NET学习全景图
  • [ vulhub漏洞复现篇 ] Celery <4.0 Redis未授权访问+Pickle反序列化利用