关于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文件如下:

 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<form action="http://127.0.0.1:8081/HelloServlet/testSession" method="post">
<input type="text" name="username" />
<input type="submit" />
</form>
</body>
</html>

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

 package com.hundsun.vivizhang.servlet;

 import java.io.IOException;

 import java.io.PrintWriter;
import java.util.Date; import javax.jws.WebService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; @WebServlet("/testSession")
public class testSession extends HttpServlet{
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#HttpServlet()
*/
public testSession() {
super();
// TODO Auto-generated constructor stub
} /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected 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>");
} /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}

此处不用配置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开发必不可少的。

关于Servlet会话跟踪的那些事儿的更多相关文章

  1. Servlet - 会话跟踪

    Servlet 标签 : Java与Web 会话跟踪 HTTP本身是"无状态"协议,它不保存连接交互信息,一次响应完成之后即连接断开,下一次请求需要重新建立连接,服务器不记录上次连 ...

  2. 7、Servlet会话跟踪

    一.会话跟踪: 不管操作多少功能,都是与当前登录用户相关的信息,当前的登录用户始终没有改变,也就是用户名和密码都没有丢失.但HTTP协议是一个无状态的协议,当一个客户向服务器发出请求(request) ...

  3. Servlet会话跟踪和Cookies及HttpSession会话

    会话只是指一段指定的时间间隔. 会话跟踪是维护用户状态(数据)的一种方式.它也被称为servlet中的会话管理. Http协议是一个无状态的,所以我们需要使用会话跟踪技术来维护用户状态. 每次用户请求 ...

  4. IT兄弟连 JavaWeb教程 Servlet会话跟踪 Session常用方法

    ●  public Object getAttribute(String name) 该方法返回在该session会话中具有指定名称的对象,如果没有指定名称的对象,则返回null. ●  public ...

  5. IT兄弟连 JavaWeb教程 Servlet会话跟踪 Session技术

    Servlet提供了HttpSession接口,该接口提供了一种跨多个页面请求或访问网站时识别用户以及存储有关用户信息的方式. Servlet容器使用这个接口来创建一个HTTP客户端和HTTP服务器之 ...

  6. IT兄弟连 JavaWeb教程 Servlet会话跟踪 Cookie常用方法

    以下是在Servlet中操作Cookie时可使用的有用的方法列表 ●  public void setDomain(String pattern) 该方法设置cookie适用的域,例如 itxdl.c ...

  7. IT兄弟连 JavaWeb教程 Servlet会话跟踪 经典面试题

    1.描述Cookie的作用 Cookie是网站保存在浏览器客户端的信息,也就是说保存在访客的机器里的变量,一般随着HTTP头发送到客户端.在Cookie生效之后及失效之前,客户每次发出页面请求的时候, ...

  8. IT兄弟连 JavaWeb教程 Servlet会话跟踪 经典案例

    案例需求:编写一个servlet,可以向session中存放一个消息,再编写一个servlet可以从session取得session中存放的这个消息. 案例实现: package com.xdl.se ...

  9. IT兄弟连 JavaWeb教程 Servlet会话跟踪 Cookie路径问题

    操作Cookie时,需要注意路径问题: 设置操作:任何路径都可以设置Cookie,但是有时我们也是用设置进行替换Cookie和删除Cookie(maxAge=0)! 替换:只能由完全相同的路径来操作! ...

随机推荐

  1. File-nodejs

    文件系统模块是一个简单包装的标准 POSIX 文件 I/O 操作方法集.您可以通过调用require('fs')来获取该模块.文件系统模块中的所有方法均有异步和同步版本. 文件系统模块中的异步方法需要 ...

  2. poj1000 A+B Problem

    Description Calculate a+b Input Two integer a,b (0<=a,b<=10) Output Output a+b Sample Input 1 ...

  3. homework-08 C++课程课后思考与练习

    经过上次晚交作业导致没分以后 我再也不敢晚交作业了 今天就把这次作业先写了 homework Part 1 1. 理解C++变量的作用域和生命周期 a) 用少于10行代码演示你对局部变量的生命周期的理 ...

  4. UVALive 7274 Canvas Painting (优先队列)

    Canvas Painting 题目链接: http://acm.hust.edu.cn/vjudge/contest/127406#problem/C Description http://7xjo ...

  5. Model First:创建实体数据模型(ADO.NET 实体数据模型)

    Microsoft Entity Framework是一个对象关系映射工具(Object Relational Mapping ,O/RM)工具.它可以让你从一个数据库自动地生成数据接入层.实体框架免 ...

  6. Erp:原料投入产出报表

    USE [ChangHongWMS612]GO /****** Object: StoredProcedure [dbo].[st_WMS_RptMaterialInOutDaily] Script ...

  7. Connection对象连接加密2

    一般情况下,大多数人习惯于将数据库连接写在web.config上里面,理论上讲,将明文存放在该文件里面是安全的,因为web.config文件是不允许被客户端下载,但一旦该文件泄漏出去,哪怕是很短的时间 ...

  8. 剑指OFFER之重建二叉树(九度OJ1385)

    题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7 ...

  9. Mysql中关于 group_concat函数详解

    group_concat()主要功能:能将相同的行组合起来 完整的语法如下: group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Sepa ...

  10. MEF 编程指南(九):部件生命周期

    理解 MEF 容器部件生命周期和实现是非常重要的事情.考虑到 MEF 关注可扩展应用程序.这变得尤为重要.生命期可以解释为期望部件的共享性(transitively, its exports)   共 ...