Java-Web基础之Session

变量命名应该要名副其实,如果名称需要注释来补充,那就不算名副其实。——《Clean Code》

Http协议的”无状态性”

Http协议是无状态的。这意味着服务器在处理完一个请求后,不会保留任何关于这个请求的上下文信息。它不记得之前发生了什么,也不关系将来会发生什么。

举例:

  1. 你第一次访问一个网站,服务器会响应你的首页
  2. 你第二次访问同一个网站的另一个页面,服务器会像第一次一样处理,它并不知道你刚刚访问过首页,也不知道你是同一个用户。
  3. 每次请求都是独立的,服务器不会记住你是谁,或者你之前做过什么

但是在实际的Web应用中,我们几乎总是需要识别用户,并维持他们的某种状态。

Session 的概念与作用

为了解决HTTP的无状态性问题,并实现在多次请求之间保持用户的状态,我们引入了Session(会话机制)。

什么是Session?

简单来说,Session是Web服务器为每个独立的用户(或浏览器会话)在服务器端分配并维护的一块独立的存储空间。这块存储空间用于保存特定用户在整个会话期间的关键数据。

  • 服务器端存储:Session数据是存储在服务器内存中的,而不是客户端
  • 唯一标识:每个Session都有一个唯一的标识符,通常称为Session ID
  • 会话范围:Session 的生命收起通常从用户第一次访问Web应用开始,到用户关闭浏览器(或达到超时时间)结束

Session如何工作

这里简单描述一下Session如何利用HTTP来实现状态保持:

  1. 用户首次请求:当用户第一次访问Web应用时,Web服务器会检测到这是一个新的会话。
  2. 创建Session:服务器会为这个用户创建一个新的Session对象,并生成一个唯一的Session ID
  3. 发生Session ID给客户端:服务器会将这个Session ID作为响应的一部分发送给客户端。最常见的方式是将其写入一个特殊的Cookie,然后发送给浏览器。
  4. 客户端存储Session ID:浏览器收到服务器发送的Cookie后,会将其存储起来。
  5. 后续请求携带Session ID:用户在同一个会话中访问该网站的其他页面时,浏览器会自动将指责给存储的Session ID Cookie 附加到后续的每一个Http请求中,发送给服务器。
  6. 服务器识别Session:服务器接收到请求后,会从请求中解析出Session ID。然后,它会根据这个Session ID到自己的内存中查找对应的Session对象。如果找到了,就说明服务器认出了这个用户,可以获取到之前存储在Session中的所有数据,从而实现状态的保持。

HttpSession 接口

HttpSession 接口时Java Servlet API 的核心组成部分,它提供了在服务器端管理和访问Session数据的方法。当你需要存储、检索或移除特定用户的数据时,都会用到它。

获取HttpSession对象

HttpServletRequest.getSession()方法

用法:

1
2
3
4
5
// 在 Servlet 的 doGet 或 doPost 方法中
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
// 此时,你可以使用 session 对象了
}

工作原理

  • 当调用 request.getSession()时,Servlet容器会首先检查当前请求中是否包含了有效的Session ID
  • 如果Session ID有效,并且服务器上存在对应的 Session对象,那么容器就会返回这个已经存在的 HttpSession对象
  • 如果没有Session ID 或Session ID已经过期,那么容器会创建一个新的 HttpSession对象,生成一个新的Session ID,并将这个Session ID封装在一个Cookie中,随着响应发给客户端

HttpServletRequest.getSession(boolean create)方法

这个方法允许你控制是否在Session不存在时创建新的Session。

1
2
3
4
5
6
7
8
// 如果 Session 不存在,则不创建,返回 null
HttpSession session = request.getSession(false);

if (session == null) {
System.out.println("Session 不存在或已失效,未创建新的 Session。");
} else {
System.out.println("Session 存在或已创建,Session ID: " + session.getId());
}
  • create = true:行为与 getSession()相同
  • create = false:当请求中没有关联的Session或者Session失效,此方法会返回null,而不会创建新的Session。

存储和获取属性(数据的读写)

HttpSession 对象就像一个 MAP容器,允许你存储任意的Java对象。

setAttribute(String name,Object value)方法

存储数据到Session。将一个对象绑定到Session中,通过一个字符串名称来标识。

  • name:属性的名称(键),类型为String
  • value:属性的值,类型为 Object。你可以存储任何可序列化的Java对象
1
2
3
4
5
6
7
8
9
10
11
// 用户登录成功后,将用户信息存入 Session
User loggedInUser = new User("zhangsan", "张三");
session.setAttribute("currentUser", loggedInUser);

// 存储一个字符串
session.setAttribute("username", "zhangsan");
// 存储购物车列表
List<String> cartItems = new ArrayList<>();
cartItems.add("Laptop");
cartItems.add("Mouse");
session.setAttribute("cart", cartItems);

getAttribute(String name)方法

通过属性名称获取存储在Session中的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 获取当前登录的用户信息
User user = (User) session.getAttribute("currentUser");
if (user != null) { //不存在时返回null
System.out.println("当前登录用户: " + user.getName());
} else {
System.out.println("用户未登录。");
}

// 获取购物车内容
List<String> myCart = (List<String>) session.getAttribute("cart");
if (myCart != null) {
System.out.println("购物车商品: " + myCart);
}

注意,getAttribute()方法返回的时 Object类型,所以你需要精细强制类型转换到你存储的原始类型。

removeAttribute(String name)方法

从Session中删除指定的属性。

1
2
3
4
// 用户登出时,移除用户信息
session.removeAttribute("currentUser");
// 清空购物车
session.removeAttribute("cart");

当你不再需要Session中的某个数据时,即使移除可以节省服务器内存。

Session ID

getId()方法

每个 HttpSession对象都有一个由服务器生成的唯一字符串ID。这个ID是服务器用来识别不同客户端的关键。

1
2
String sessionId = session.getId();
System.out.println("当前 Session ID: " + sessionId);

Session生命周期管理

setMaxInactiveInterval(int interval)方法

设置Session最大不活动时间。这个方法设置Session在不活跃(即没有客户端请求与该Session关联)多少秒后失效。

1
2
// 设置Session 在30分钟(30 * 60 秒)不活跃后失效
session.setMaxInactiveInterval(30 * 60) // 比1800 更加直观,容易理解
  • interval参数以秒为单位。如果设置为0或负数,表示Session将永不失效。
  • 默认超时时间:Web应用服务器通常由默认的Session超时时间(如30分钟),也可以在web.xml中进行全局配置。

invalidata()方法

使Session立即失效。这个方法会立即终止当前的Session,并从服务器内容中移除所有与之关联的数据。

1
2
3
// 用户登出时,使Session失效
session.invalidate();
System.out.println("Session 已失效");
  • Session销毁后,Session中的所有属性都将被移除,且该Session ID不再有效。后续客户端再带着该Session ID发送请求,服务器会认为这是一个新的会话,并可能创建一个新的Session。

Cookie

Cookie是一种由服务器发送到用户浏览器并存储在浏览器本地的小数据块。当浏览器再次向同一服务发送请求时,它会自动将这个Cookie连同请求一起发送回服务器。

一个由tomcat设置的Cookie如下:

1
JSESSIONID=9004779DB74ABEDE4EE560883B841AFB
  • 客户端存储:Cookie数据是存储在客户端浏览器上的。
  • 大小限制:通常每个Cookie有大小限制(如4KB),且每个域名下的Cookie数量也有限制。
  • 生命周期:Cookie可以设置为会话级别的

Session ID通过Cookie传递的详细过程

  1. 用户首次访问:

    • 当用户访问一个Web应用时,浏览器发送一个不带任何Session ID的HTTP请求给服务器。

    • 当在请求处理流程中执行 HttpServletRequest.getSession()语句后,就会在服务器内存中为这个新用户创建一个新的 HttpSession对象。

    • 服务器为这个新的Session生成一个唯一的Session ID。

    • 在服务器返回给浏览器的HTTP响应中,服务器会添加一个 Set-Cookie响应头。这个 Set-Cookie头会包含生成的Session ID,通常以 JSESSIONID(这是Java Servlet 规范默认的SessionID Cookie名称)作为键名。

      1
      2
      3
      4
      5
      // 服务器响应头示例
      HTTP/1.1 200 OK
      Content-Type: text/html;charset=UTF-8
      Set-Cookie: JSESSIONID=ABCDEF1234567890; Path=/myWebApp; HttpOnly
      ...
  2. 浏览器存储Cookie:

    • 浏览器接收到服务器的响应后,会解析Set-Cookie头,并将Cookie中的内容储存在本地。
  3. 用户后续请求:

    • 当用户在同一个浏览器会话中,再次向同一个Web应用发送请求时,浏览器会自动查找并把之前存储的 JSESSIONID Cookie添加到HTTP请求头中,发送给服务器。

      1
      2
      3
      4
      5
      6
      // 浏览器请求头示例
      GET /myWebApp/products HTTP/1.1
      Host: example.com
      Cookie: JSESSIONID=ABCDEF1234567890
      User-Agent: ...
      ...
  4. 服务器识别Session:

    • 服务器接收到请求后,会从请求中读取 Cookie字段,并解析出 JSESSIONID的值。
    • 服务器使用这个SessionID去查找其内存中是否有对应的HttpSession对象。

Session演示Demo

xxy1103/javaWeb at Session


Java-Web基础之Session
http://blog.ulna520.com/2025/07/27/Java-Web基础之Session_20250727_105620/
Veröffentlicht am
July 27, 2025
Urheberrechtshinweis