JSP Session 完整教程
目录
- 什么是 Session?
- 为什么需要 Session?
- Session 的工作原理
- JSP 中如何使用 Session?
- 获取 Session 对象
- 存储数据到 Session
- 从 Session 获取数据
- 移除 Session 中的数据
- 销毁整个 Session
- 一个完整的登录验证示例
- Session 的生命周期和超时
- Session vs. Cookie
- 最佳实践与注意事项
什么是 Session?
在 Web 应用中,Session(会话) 是一种服务器端的技术,用于在多个页面请求之间保存用户的状态信息。

你可以把它想象成一个“用户专属的临时储物柜”,当一个用户访问你的网站时,服务器会为他创建一个独一无二的 Session 对象,并分配一个唯一的 ID(称为 Session ID),之后,该用户在同一个浏览器会话中访问的所有页面,都可以共享这个“储物柜”里的东西。
核心特点:
- 服务器端存储:数据存储在服务器上,客户端(浏览器)只持有 Session ID。
- 基于 Cookie:默认情况下,Session ID 通过 Cookie 在浏览器和服务器之间传递。
- 有生命周期:Session 不是永久的,它会在一段时间后自动失效(超时),或者可以被手动销毁。
- 用户隔离:每个用户的 Session 都是独立的,互不干扰。
为什么需要 Session?
HTTP 协议本身是无状态的,这意味着服务器不会记住任何关于前一个请求的信息,每次请求都是全新的、独立的。
- 用户登录成功(请求 A)。
- 服务器验证用户名密码,告诉他“登录成功”。
- 用户点击“个人中心”链接(请求 B)。
- 服务器收到请求 B,它不知道这个用户是谁,也不知道他刚刚登录过,他需要再次验证身份。
Session 就是为了解决这个问题而生的。 在请求 A 中,服务器将“用户已登录”这个状态信息存入 Session,当请求 B 到达时,服务器通过请求中携带的 Session ID 找到对应的 Session,发现里面有“用户已登录”的信息,于是直接允许他访问个人中心,无需再次登录。

常见的 Session 应用场景:
- 用户登录状态管理:记录用户是否已登录。
- 购物车:在用户浏览不同商品页面时,保存他已选择的商品。
- 存储用户偏好设置:如语言、主题等。
- 防止表单重复提交:在提交后,将一个标记存入 Session,页面刷新时检查该标记。
Session 的工作原理
-
创建 Session:当某个 JSP 页面第一次调用
request.getSession()方法时(或类似的 API),服务器会检查请求中是否包含有效的 Session ID。- 如果没有,服务器会创建一个新的
HttpSession对象,并生成一个唯一的 Session ID(A1B2C3D4E5F6)。 - 如果有,服务器会根据这个 ID 查找对应的 Session 对象,如果找到且未超时,则直接使用该对象。
- 如果没有,服务器会创建一个新的
-
传递 Session ID:服务器会将这个 Session ID 通过 Cookie 发送给客户端,并设置
Cookie的名称通常为JSESSIONID,浏览器会自动保存这个 Cookie。 -
后续请求:在同一个浏览器会话中,用户之后的每一次请求(点击链接、刷新页面等),浏览器都会自动带上这个
JSESSIONIDCookie。 -
服务器识别:服务器收到后续请求后,会读取
JSESSIONIDCookie,并根据这个 ID 找到之前创建的 Session 对象,从而实现跨请求的状态保持。
注意:如果用户禁用了浏览器 Cookie,默认的 Session 机制会失效,但 Tomcat 等服务器会提供一种 URL 重写(URL Rewriting)的机制作为备选,即 Session ID 会直接附加在 URL 后面(
index.jsp;jsessionid=A1B2C3D4E5F6)。
JSP 中如何使用 Session?
在 JSP 中,session 是一个内置对象,类型为 javax.servlet.http.HttpSession,你无需手动创建它,可以直接使用。
1 获取 Session 对象
虽然可以直接使用 session 内置对象,但为了清晰,也可以显式获取:
HttpSession session = request.getSession();
request.getSession(true)(或request.getSession()):Session 不存在,会创建一个新的,这是最常用的方式。request.getSession(false):Session 不存在,则返回null,不会创建新的。
2 存储数据到 Session
使用 session.setAttribute(String name, Object value) 方法。name 是一个字符串键,value 是任意 Java 对象。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>设置 Session 数据</title>
</head>
<body>
<h1>设置 Session 数据</h1>
<%
// 1. 获取 session 对象 (如果不存在会自动创建)
HttpSession session = request.getSession();
// 2. 存储数据
String username = "张三";
session.setAttribute("username", username);
// 也可以存储更复杂的数据,比如一个 User 对象
// User user = new User("李四", "user@example.com");
// session.setAttribute("user", user);
out.println("用户名 '" + username + "' 已存入 Session。");
%>
<br>
<a href="get_session_data.jsp">点击此处获取 Session 数据</a>
</body>
</html>
3 从 Session 获取数据
使用 session.getAttribute(String name) 方法,它会返回一个 Object 对象,所以需要进行类型转换。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>获取 Session 数据</title>
</head>
<body>
<h1>获取 Session 数据</h1>
<%
// 从 session 中获取数据
Object usernameObj = session.getAttribute("username");
if (usernameObj != null) {
// 需要进行类型转换
String username = (String) usernameObj;
out.println("从 Session 中获取到的用户名是: <strong>" + username + "</strong>");
} else {
out.println("Session 中没有找到 'username' 属性。");
}
%>
</body>
</html>
4 移除 Session 中的特定数据
使用 session.removeAttribute(String name) 方法,这只会删除指定的属性,Session 对象本身仍然存在。
<%
session.removeAttribute("username");
out.println("Session 中的 'username' 属性已被移除。");
%>
5 销毁整个 Session
使用 session.invalidate() 方法,这会立即销毁当前 Session 对象,并清除其中所有绑定的数据,通常用于“安全退出”功能。
<%
// 销毁整个 session
session.invalidate();
out.println("Session 已销毁,您已安全退出。");
// 通常销毁后会重定向到登录页面或首页
// response.sendRedirect("login.jsp");
%>
一个完整的登录验证示例
这个例子将展示如何结合 Session 和表单实现一个简单的登录功能。
文件结构:
/your-project
|-- login.jsp (登录页面)
|-- dashboard.jsp (需要登录才能访问的页面)
|-- logout.jsp (登出页面)
|-- WEB-INF/
|-- web.xml
login.jsp (登录表单)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>登录</title>
</head>
<body>
<h1>用户登录</h1>
<%-- 检查是否已有登录信息,有则提示 --%>
<% if (session.getAttribute("username") != null) { %>
<p style="color: red;">您已经登录了!</p>
<% } %>
<form action="login_check.jsp" method="post">
用户名: <input type="text" name="username" required><br>
密码: <input type="password" name="password" required><br>
<input type="submit" value="登录">
</form>
</body>
</html>
login_check.jsp (后台验证逻辑)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
// 简单的硬编码验证
if ("admin".equals(username) && "password123".equals(password)) {
// 验证成功,将用户名存入 session
session.setAttribute("username", username);
out.println("<script>alert('登录成功!'); window.location.href='dashboard.jsp';</script>");
} else {
// 验证失败,返回登录页面
out.println("<script>alert('用户名或密码错误!'); window.location.href='login.jsp';</script>");
}
%>
dashboard.jsp (受保护页面)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>用户中心</title>
</head>
<body>
<%
// 检查 session 中是否存在 username 属性
if (session.getAttribute("username") == null) {
// 如果不存在,说明用户未登录,重定向到登录页
response.sendRedirect("login.jsp");
return; // 停止执行后续代码
}
%>
<h1>欢迎, <%= session.getAttribute("username") %>!</h1>
<p>这是一个受保护的页面,只有登录用户才能看到。</p>
<a href="logout.jsp">安全退出</a>
</body>
</html>
logout.jsp (登出逻辑)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
// 销毁 session
session.invalidate();
// 重定向到登录页
response.sendRedirect("login.jsp");
%>
Session 的生命周期和超时
- 创建:第一次调用
request.getSession()时创建。 - 活动:有客户端请求与该 Session 关联时,Session 处于活动状态。
- 超时:如果在一个指定的时间内,客户端没有发出任何与该 Session 关联的请求,服务器会认为该 Session 已闲置,并自动将其销毁,这个时间就是超时时间。
- 销毁:可以通过
session.invalidate()手动销毁,或者超时后自动销毁。
如何设置 Session 超时时间?
-
在 JSP/Servlet 中设置(单位:秒)
<%-- 设置 Session 超时时间为 30 分钟 (1800秒) --%> <% session.setMaxInactiveInterval(1800); %> -
在
web.xml中全局设置(推荐) 这会影响整个应用中所有的 Session。<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!-- 设置 Session 超时时间为 30 分钟 --> <session-config> <session-timeout>30</session-timeout> </session-config> </web-app>
Session vs. Cookie
| 特性 | Session | Cookie |
|---|---|---|
| 存储位置 | 服务器端 | 客户端 (浏览器) |
| 安全性 | 高,敏感数据不经过网络。 | 低,数据存储在客户端,可能被窃取或篡改。 |
| 存储容量 | 大,只受服务器内存限制。 | 小,通常限制在 4KB 左右。 |
| 数据类型 | 可以存储任意 Java 对象。 | 通常只能存储字符串。 |
| 生命周期 | 可配置超时时间,也可手动销毁。 | 可以设置为会话级(关闭浏览器失效)或持久化(长期有效)。 |
| 依赖关系 | 通常依赖 Cookie 来传递 Session ID。 | 独立,不依赖其他技术。 |
- Session 适合存储敏感、重要、量大的用户状态数据,如登录信息、购物车。
- Cookie 适合存储少量、非敏感、需要长期保存的数据,如用户的主题偏好、上次访问时间等。
最佳实践与注意事项
- 及时清理:当不再需要 Session 中的数据时(例如用户登出后),使用
session.invalidate()或session.removeAttribute()及时清理,避免占用服务器内存。 - 避免存储大量数据:Session 存储在服务器内存中,如果每个用户都存大量数据,会迅速消耗服务器资源,影响性能,对于大型数据,应考虑数据库或缓存(如 Redis)。
- 注意线程安全:在一个多线程的 Web 容器中,一个
HttpSession对象不能被多个线程同时修改,如果多个请求(如多个标签页)同时修改同一个 Session 的属性,可能会导致数据不一致,应避免在 Session 中存储可变的状态。 - 处理禁用 Cookie 的情况:如果你的应用必须支持禁用 Cookie 的浏览器,确保你的链接是 Session 友好的,虽然 Tomcat 默认会处理 URL 重写,但在手动构造链接时,可以使用
response.encodeURL()来自动附加 Session ID。<a href="<%= response.encodeURL("protected_page.jsp") %>">受保护的链接</a> - 不要滥用 Session:不是所有数据都需要存入 Session,只存储真正需要在多个请求间共享的状态信息。
希望这份详细的教程能帮助你完全理解和使用 JSP Session!
