JavaWeb的session及其共享技术

本文详细介绍了JavaWeb中的会话概念,重点讨论了cookie和session的工作原理、常用方法、应用场景以及局限性。在session共享部分,探讨了基于数据库、Cookie和Memcache的实现方式,为读者提供了深入理解session管理的指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.什么叫会话

​ 一次会话指的是:就好比打电话,A给B打电话,接通之后,会话开始,直到挂断电话,该次会话就结束了,而浏览器访问服务器,就跟打电话一样,浏览器A给服务器发送请求,访问web程序,该次会话就已经接通,其中不管浏览器发送多少请求(就相当于接通电话后说话一样),都视为一次会话,直到浏览器关闭,本次会话结束。

​ 其中注意,一个浏览器就相当于一部电话,如果使用火狐浏览器,访问服务器,就是一次会话了,然后打开google浏览器,访问服务器,这是另一个会话,虽然是在同一台电脑,同一个用户在访问,但是,这是两次不同的会话。

2.引入cookie和session

​ 思考一个问题,一个浏览器访问一个服务器就能建立一个会话,如果别的电脑,都同时访问该服务器,就会创建很多会话,就拿一些购物网站来说,我们访问一个购物网站的服务器,会话就被创建了,然后就点击浏览商品,对感兴趣的商品就先加入购物车,等待一起付账,这看起来是很普通的操作,但是想一下,如果有很多别的电脑上的浏览器同时也在访问该购物网站的服务器,跟我们做类似的操作呢?服务器又是怎么记住用户,怎么知道用户A购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,不能放入用户B或用户C的购物车内的呢?

​ 这里我们就用cookie和session两种会话跟踪技术来跟踪整个会话。

3.cookie简介

3.1.cookie的工作原理

在这里插入图片描述

1)首先浏览器向服务器发出请求。

2)服务器就会根据需要生成一个Cookie对象,并且把数据保存在该对象内。

3)然后把该Cookie对象放在响应头,一并发送回浏览器。

4)浏览器接收服务器响应后,提出该Cookie保存在浏览器端。

5)当下一次浏览器再次访问那个服务器,就会把这个Cookie放在请求头内一并发给服务器。

  1. 服务器从请求头提取出该Cookie,判别里面的数据,然后作出相应的动作。

3.2.cookie中的常用方法

Cookie cookie=new Cookie(String name,String value) 构造一个cookie对象

response.addCookie(Cookie cookie) 是将一个cookie对象传入客户端。

request.getCookies() 得到所有的cookie对象

cookie.getName() 得到此cookie对象的名字

cookie.getValue() 得到对应名称的cookie的值

cookie.setMaxAge() 设置过期时间

3.3.案例

@WebServlet("/CookieServletDemo1")
public class CookieServletDemo1 extends HttpServlet {
  private static final long serialVersionUID = 1L;

  /**
	 * @see HttpServlet#HttpServlet()
	 */
  public CookieServletDemo1() {
    super();
    // TODO Auto-generated constructor stub
  }

  /**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    // 创建cookie对象
    // cookie中`存放的数据以键值对存在map<String,String> 键和值都只能是字符串,不支持中文
    Cookie cookie = new Cookie("username", "zhangsan");
    Cookie cookie1 = new Cookie("password", "1234");
    // 失效时间 以秒为单位
    cookie.setMaxAge(60 * 60);
    response.addCookie(cookie);
    response.addCookie(cookie1);
  }

  /**
	 * @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);
  }

}
@WebServlet("/CookieServletDemo2")
public class CookieServletDemo2 extends HttpServlet {
  private static final long serialVersionUID = 1L;

  /**
	 * @see HttpServlet#HttpServlet()
	 */
  public CookieServletDemo2() {
    super();
    // TODO Auto-generated constructor stub
  }

  /**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    //		从请求头中获取cookie信息
    Cookie[] cookies = request.getCookies();
    for(Cookie c:cookies){
      System.out.println(c.getName()+"===="+c.getValue());
    }
  }

  /**
	 * @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);
  }

}

3.4.浏览器中查看cookie

不同的浏览器略有差别,这里以谷歌浏览器为例。

F12打开开发者工具 —点击Application选项—选中其中的cookie—选择相应的站点—看到该站点中的所有cookie信息。

3.5.cookie的应用场景

​ cookie的应用场景有很多,最具代表性的当属网站的记录用户账号和密码的功能了,大家可能经常看到登录某某论坛,某某网站时,下面有个选项为N天内自动登录,其实这就是cookie的应用。当用户第一次输入账号密码时给服务器发送请求时,服务器会根据账号密码回写一个字符串cookie,当用户下次再向该服务器发送登录请求时,则带着这个字符串cookie一起去访问服务器,这时,服务器只需要对比次字符串和数据库中存储的字符串是否相同,则可以达到用户自动登录功能。

3.6.cookie的局限性

  • Cookie数量和长度的限制。每个站点最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉。
  • cookie中只能存字符串。且不支持中文
  • cookie不适合保存敏感数据(例如密码)可见的

4.session

4.1.session的工作原理

在这里插入图片描述

1)浏览器发出请求到服务器。

2)服务器会根据需求生成Session对象,并且给这个Session对象一个编号,一个编号对应一个Session对象

3)服务器把需要记录的数据封装到这个Session对象里,然后把这个Session对象保存下来。

4)服务器把这个Session对象的编号放到一个Cookie里,随着响应发送给浏览器

5)浏览器接收到这个cookie就会保存下来

6)当下一次浏览器再次请求该服务器服务,就会发送该Cookie

7)服务器得到这个Cookie,取出它的内容,它的内容就是一个Session的编号!!!

8)凭借这个Session编号找到对应的Session对象,然后利用该Session对象把保存的数据取出来!

4.2.session的常用方法

方法解释
void setAttribute(String attribute, Object value)设置Session属性。value参数可以为任何Java Object。通常为Java Bean。value信息不宜过大
String getAttribute(String attribute)返回Session属性
void removeAttribute(String attribute)移除Session属性
String getId()返回Session的ID。该ID由服务器自动创建,不会重复
long getCreationTime()返回Session的创建日期。
long getLastAccessedTime()返回Session的最后活跃时间。返回类型为long
int getMaxInactiveInterval()返回Session的超时时间。单位为秒。超过该时间没有访问,服务器认为该Session失效
void setMaxInactiveInterval(int second)设置Session的超时时间。单位为秒4.3.

4.3.案例

@WebServlet("/SeesionServletDemo1")
public class SeesionServletDemo1 extends HttpServlet {
  private static final long serialVersionUID = 1L;

  /**
	 * @see HttpServlet#HttpServlet()
	 */
  public SeesionServletDemo1() {
    super();
    // TODO Auto-generated constructor stub
  }

  /**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

    // 创建session对象
    HttpSession session = request.getSession();
    System.out.println(session.getId());

    session.setAttribute("name", "zhangsan");

    session.setAttribute("student", new Student(1, "zhangsan", 12));
    Student stu = (Student) session.getAttribute("student");

    stu.setName("lisi");

    // 设置过期时间 单位是秒
    //		session.setMaxInactiveInterval(2);
    // 直接销毁session  注销登录
    //		session.invalidate();

  }

  /**
	 * @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);
  }

}
public class Student {

  private Integer id;
  private String name;
  private Integer age;
  public Integer getId() {
    return id;
  }
  public void setId(Integer id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public Integer getAge() {
    return age;
  }
  public void setAge(Integer age) {
    this.age = age;
  }
  public Student(Integer id, String name, Integer age) {
    super();
    this.id = id;
    this.name = name;
    this.age = age;
  }
  public Student() {
    super();
    // TODO Auto-generated constructor stub
  }
}
@WebServlet("/SeesionServletDemo2")
public class SeesionServletDemo2 extends HttpServlet {
  private static final long serialVersionUID = 1L;

  /**
	 * @see HttpServlet#HttpServlet()
	 */
  public SeesionServletDemo2() {
    super();
    // TODO Auto-generated constructor stub
  }

  /**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

    // 创建session对象
    HttpSession session = request.getSession();

    System.out.println(session.getAttribute("name"));

    Student stu = (Student) session.getAttribute("student");
    System.out.println(stu.getName());

  }

  /**
	 * @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);
  }

}

4.4.session的生命周期

session对象生命周期:

  • session对象什么创建?
    • 执行request.getSession()方法时
  • session对象什么销毁?
    • 默认情况下,session对象在30分钟之后服务器自动销毁。
    • 手动设置session有效时长
      • void setMaxInactiveInterval(int interval) -以秒为单位。
    • 手动销毁
      • void invalidate()

4.5.session在一次会话结束后消失的原因

​ 由于session的使用需要依赖cookie,cookie每次从浏览器端传输session的id到后台,然后查找对应编号的session进行使用,但由于此时的cookie默认的失效时间是一次会话,当一次会话结束后,存放id的cookie对象就消失了,下一次会话访问时就会生成新的id,那存储在原来的session对象中的数据就无法找到了。

4.6.浏览器禁用cookie能否使用session

可以,但需要手动拼接id传过去,例如

http://localhost:8080/day06/session.jsp;jsessionid=AE62ECBAAD2CA16DA6AEBF1D1527CD45

jsessionid指的就是session对应的id

4.7.session共享

4.7.1.基于数据库的Session共享

首选当然是大名鼎鼎的Mysql数据库,并且建议使用内存表Heap,提高session操作的读写效率。这个方案的实用性比较强,相信大家普遍在使用,它的缺点在于session的并发读写能力取决于Mysql数据库的性能,同时需要自己实现session淘汰逻辑,以便定时从数据表中更新、删除 session记录,当并发过高时容易出现表锁,虽然我们可以选择行级锁的表引擎,但不得不否认使用数据库存储Session还是有些杀鸡用牛刀的架势。

4.7.2.基于Cookie的Session共享

​ 这个方案我们可能比较陌生,但它在大型网站中还是比较普遍被使用。原理是将全站用户的Session信息加密、序列化后以Cookie的方式, 统一种植在根域名下(如:.host.com),利用浏览器访问该根域名下的所有二级域名站点时,会传递与之域名对应的所有Cookie内容的特性,从而实现 用户的Cookie化Session 在多服务间的共享访问。

这个方案的优点无需额外的服务器资源;缺点是由于受http协议头信心长度的限制,仅能够存储小部分的用户信息,同时Cookie化的 Session内容需要进行安全加解密(如:采用DES、RSA等进行明文加解密;再由MD5、SHA-1等算法进行防伪认证),另外它也会占用一定的带宽资源,因为浏览器会在请求当前域名下任何资源时将本地Cookie附加在http头中传递到服务器。

4.7.3.基于Memcache的Session共享

Memcache由于是一款基于Libevent多路异步I/O技术的内存共享系统,简单的Key + Value数据存储模式使得代码逻辑小巧高效,因此在并发处理能力上占据了绝对优势,目前本人所经历的项目达到2000/秒 平均查询,并且服务器CPU消耗依然不到10%。

另外值得一提的是Memcache的内存hash表所特有的Expires数据过期淘汰机制,正好和Session的过期机制不谋而合,降低了 过期Session数据删除的代码复杂度,对比“基于数据库的存储方案”,仅这块逻辑就给数据表产生巨大的查询压力。

 
更多资深讲师相关课程资料、学习笔记请入群后向管理员免费获取,更有专业知识答疑解惑。入群即送价值499元在线课程一份。
QQ群号:560819979
敲门砖(验证信息):醉渔唱晚

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值