1、概述

  • Session 表示会话,不只是在 Javaweb 中存在,只要是 web 开发,都会有会话这种机制
  • 在 Java 中会话对应的类型是:javax.servlet.http.HttpSession,简称 session/会话
  • Cookie 可以将会话状态保存在客户端,HttpSession 可以将会话状态保存在服务端
  • HttpSession 对象是一个会话级别的对象,一次会话对应一个 HttpSession 对象
  • 什么是一次会话?
    • 一般多数情况下,是这样描述的:用户打开浏览器,在浏览器上进行一些操作,然后将浏览器关闭,表示一次会话结束
    • 本质上描述:从 Session 对象的创建,到最终 session 对象超时之后销毁,这个才是真正意义的一次完整会话
  • 在会话进行过程中,web服务器一直为当前这个用户维护着一个会话对象/ HttpSession
  • 在 web 容器中,web 容器维护了大量的 HttpSession 对象,换句话说,在 web 容器中应该有一个“Session列表”
  • 思考:为什么当前会话中的每一次请求可以获取到属于自己的会话对象?session 实现原理?

2、session 实现原理

  • 打开浏览器,在浏览器上发送首次请求
  • 服务器会创建一个 HttpSession 对象,该对象代表一次会话
  • 同时生成 HttpSession 对象对应的 Cookie 对象,并且 Cookie 对象的 name 是 JSESSIONID,Cookie 的 value 是32位长度的字符串
  • 服务器将 Cookie 的 value 和 HttpSession 对象绑定到 session 列表中
  • 服务器将 Cookie 完整发送给浏览器客户端
  • 浏览器客户端将 Cookie 保存到缓存中
  • 只要浏览器不关闭,Cookie 就不会消失
  • 当再次发送请求的时候,会自动提交缓存当中的 Cookie
  • 服务器接收到 Cookie 验证该 Cookie 的 name 确实是 JSESSIONID ,然后获取该 Cookie 的 value
  • 通过 Cookie 的 value 去 session 列表中检索对应的 HttpSession 对象

2.png

  • 和 HttpSession 对象关联的这个 Cookie 的 name 是比较特殊的,在 Java 中就叫做 jsessionid

3、浏览器禁用Cookie的后果

  • 浏览器禁用 Cookie ,则浏览器缓存中将不再保存 Cookie
  • 导致在同一个会话中,无法获取到对应的会话对象
  • 禁用 Cookie 之后,每一次获取的会话对象都是新的
  • 浏览器禁用 Cookie 之后,如果还想拿到对应的 Session 对象,必须使用 URL 重写机制
  • 重写 URL 会给编程带来难度/复杂度,所以一般的 web 站点是不建议禁用 Cookie 的

4、几个问题

  1. 浏览器关闭之后,服务器端对应的 Session 对象会被销毁吗?为什么?

    • 浏览器关闭之后,服务器不会销毁 session 对象
    • 因为 B/S 架构的系统基于 HTTP 协议,而 HTTP 协议是一种无连接/无状态的协议
    • 什么是无连接/无状态?
      • 请求的瞬间,浏览器和服务器之间的通道是打开的,请求响应结束之后,通道关闭
      • 这样做的目的是降低服务器的压力
  2. session 对象在什么时候被销毁?


  • web 系统中引入了 session 超时的概念
  • 当很长一段时间(这个时间可以配置)没有用户再访问该 session 对象,此时 session 对象超时,web 服务器自动回收 session 对象
  • 可配置:web.xml 文件中,默认是30分钟
    1. <session-config>
    2. <session-timeout>120</session-timeout>
    3. </session-config>

  1. 关于 javax.servlet.http.HttpSession 接口中常用方法:
void setAttribute(String name,Object value)
Object getAttribute(String name)
void removeAttribute(String name)
void invalidate()

5、三大接口对比

  • ServletContext、HttpSession、HttpServletRequest 接口的对比
  1. 以上都是范围对象

    • ServletContext:application;是应用范围
    • HttpSession:session;是会话范围
    • HttpServletRequest:request;是请求范围
  2. 三个范围大小的排序

    • application > session > request
  3. 对数据的共享

    • application 完成跨会话共享数据
    • session 完成跨请求共享数据,但是这些请求必须在同一个会话中
    • request 完成跨 Servlet 共享数据,但是这些 Servlet 必须在同一个请求当中【转发】
  4. 使用原则:由小到大尝试,优先使用小范围

    • 例如:登录成功之后,已经登录的状态需要保存起来,可以将登录成功的这个状态保存到 session 对象中
    • 登录成功状态不能保存到 request 范围中,因为一次请求对应一个新的 request 对象
    • 登录成功状态也不能保存到 application 范围中,因为登录成功状态是属于会话级别的,不能所有用户共享

6、补充HttpServletRequest中的方法

HttpSession session = request.getSession();//获取当前的session,获取不到,则新建session
HttpSession session = request.getSession(true);//获取当前的session,获取不到,则新建session
HttpSession session = request.getSession(false);//获取当前session,获取不到,则返回null

image.png