会话和域
会话和域
Cookie
-
Cookie的基本概念
- Cookie 是一小段文本数据(通常不超过 4KB),由服务器发送到客户端并存储在客户端。
- 每次客户端向服务器发送请求时,会自动将符合条件的 Cookie 附加到请求头中。
- 在Cookie中,键和值通常是以字符串的形式存放的
-
Cookie 的作用
- 会话管理:跟踪用户的登录状态。
- 个性化设置:存储用户的偏好设置(如语言、主题等)。
- 用户行为跟踪:记录用户的浏览行为(如广告跟踪)。
-
Cookie 的特点
- 存储在客户端:Cookie 存储在浏览器中,而不是服务器。
- 键值对形式:Cookie 以键值对的形式存储数据。
- 作用域限制:Cookie 可以设置作用域(域名和路径),限制其在特定请求中发送。
- 有效期:Cookie 可以设置过期时间,可以是会话级别的(浏览器关闭后失效)或持久性的(在指定时间内有效)。
- 作用范围:Cookie在该项目下有效,关闭浏览器或者清除Cookie后失效
-
Cookie 的工作流程
- 服务器创建 Cookie:服务器通过 HTTP 响应头
Set-Cookie将 Cookie 发送到客户端。 - 客户端存储 Cookie:客户端(浏览器)将 Cookie 存储在本地的 Cookie 存储区。
- 客户端发送 Cookie:在后续请求中,客户端会自动将符合条件的 Cookie 附加到 HTTP 请求头
Cookie中。 - 服务器读取 Cookie:服务器从请求头中读取 Cookie 并处理。
- 服务器创建 Cookie:服务器通过 HTTP 响应头
-
Cookie的使用
-
设置Cookie
-
import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/setCookie") public class SetCookieServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { // 创建 Cookie Cookie cookie = new Cookie("username", "JohnDoe"); // 设置 Cookie 属性 cookie.setPath("/"); cookie.setMaxAge(3600); // 1 小时有效期 cookie.setHttpOnly(true); cookie.setSecure(true); // 添加 Cookie 到响应 response.addCookie(cookie); // 返回响应 response.getWriter().write("Cookie has been set!"); } } -
读取Cookie
-
如果没有Cookie则为null,所以需要判断是否为null
-
@WebServlet("/readCookie") public class ReadCookieServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { // 获取所有 Cookie Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if ("username".equals(cookie.getName())) { response.getWriter().write("Username: " + cookie.getValue()); return; } } } response.getWriter().write("Cookie not found!"); } }
-
Session
-
session的概念
- Session 是服务器为每个用户创建的一个存储空间,用于在多个请求之间保存用户的状态信息。
- 每个 Session 都有一个唯一的 Session ID,用于标识不同的用户会话。
- Session的键为字符串,值为Object对象
-
Session 的作用
- 会话管理:跟踪用户的登录状态。
- 数据共享:在多个请求之间共享用户数据。
- 安全性:敏感数据存储在服务器端,避免直接暴露给客户端。
-
Session 的特点
- 存储在服务器端:Session 数据存储在服务器内存或持久化存储中。
- 依赖 Session ID:客户端通过 Session ID 与服务器端的 Session 数据关联。
- 生命周期:Session 从创建到销毁有一个明确的生命周期。
-
Session 的工作原理
- 创建 Session:用户第一次访问服务器时,服务器为该用户创建一个 Session,并生成唯一的 Session ID。
- 发送 Session ID:服务器将 Session ID 通过 Cookie 或 URL 重写的方式发送到客户端。
- 客户端存储 Session ID:客户端保存 Session ID,并在后续请求中将其发送回服务器。
- 通过 Set-Cookie 响应头设置JSESSIONID
- URL 重写
- 隐藏表单字段
- 服务器识别 Session:服务器根据 Session ID 找到对应的 Session 数据。
- 销毁 Session:Session 在超时或显式销毁时被删除。
session的API
-
在 Java Servlet 中,Session 通过
HttpSession接口进行操作。以下是常用的方法 -
获取Session
-
HttpSession session = request.getSession(); // 获取当前 Session,如果不存在则创建 HttpSession session = request.getSession(false); // 获取当前 Session,如果不存在则返回 null
-
-
设置和获取 Session 属性
-
session.setAttribute("key", value); // 设置 Session 属性 Object value = session.getAttribute("key"); // 获取 Session 属性 session.removeAttribute("key"); // 移除 Session 属性
-
-
获取 Session 信息
-
String sessionId = session.getId(); // 获取 Session ID long creationTime = session.getCreationTime(); // 获取 Session 创建时间 long lastAccessedTime = session.getLastAccessedTime(); // 获取上次访问时间 int maxInactiveInterval = session.getMaxInactiveInterval(); // 获取 Session 超时时间(秒)
-
-
销毁 Session
-
session.invalidate(); // 销毁 Session
-
-
超时配置
-
session.setMaxInactiveInterval(1800); // 超时时间为 1800 秒(30 分钟) -
<session-config> <session-timeout>30</session-timeout> <!-- 超时时间为 30 分钟 --> </session-config>
-
域对象
Request(请求域)
- 作用范围
- 范围:当前请求内有效。
- 生命周期:从客户端发起请求到服务器返回响应。
- 主要功能
- 在同一个请求的多个组件(如 Servlet、JSP、过滤器)之间共享数据。
- 常用于请求转发(Forward)或包含(Include)时传递数据。
Session(会话域)
- 作用范围
- 范围:当前用户的会话内有效。
- 生命周期:从用户访问服务器开始,到会话超时或显式销毁。
- 主要功能
- 在同一个用户的多个请求之间共享数据。
- 常用于存储用户登录信息、购物车数据等。
- 作用范围
- 范围:整个 Web 应用内有效。
- 生命周期:从 Web 应用启动到应用关闭。
- 主要功能
- 在整个 Web 应用的所有用户和请求之间共享数据。
- 常用于存储全局配置、共享资源等。
Application(应用域)
域对象的比较
| 域对象 | 作用范围 | 生命周期 | 适用场景 |
|---|---|---|---|
| Request | 当前请求 | 请求开始到响应结束 | 请求转发或包含时传递数据 |
| Session | 当前用户的会话 | 会话开始到会话超时或销毁 | 用户登录状态、购物车数据 |
| Application | 整个 Web 应用 | 应用启动到应用关闭 | 全局配置、共享资源 |
ThreadLocal
- Tomcat 使用线程池来处理并发请求。当用户发起请求时,Tomcat 会从线程池中分配一个线程来处理该请求。处理完成后,线程会被释放并返回到线程池中,供后续请求使用。
- 也就是说一个用户对应一个线程
ThreadLocal 的作用:
ThreadLocal的主要作用是:- 线程隔离:为每个线程提供一个独立的变量副本,避免线程间共享变量。
- 简化线程安全:通过线程隔离,避免了使用同步机制(如
synchronized或Lock)来保证线程安全。 - 传递上下文信息:在复杂的多线程场景中,可以通过
ThreadLocal传递上下文信息(如用户会话、事务信息等)。
ThreadLocal的核心方法是:set(T value):设置当前线程的变量副本。get():获取当前线程的变量副本。remove():移除当前线程的变量副本。
ThreadLocal 的典型应用场景:
-
数据库连接管理
- 在数据库连接池中,可以使用
ThreadLocal为每个线程分配一个独立的数据库连接,避免线程间共享连接。
- 在数据库连接池中,可以使用
-
用户会话管理
- 在 Web 应用中,可以使用
ThreadLocal存储当前用户的会话信息(如用户 ID、权限等)。
- 在 Web 应用中,可以使用
-
事务管理
- 在事务管理中,可以使用
ThreadLocal传递事务上下文信息。
- 在事务管理中,可以使用
-
日期格式化
SimpleDateFormat是线程不安全的,可以使用ThreadLocal为每个线程分配一个独立的SimpleDateFormat实例。
ThreadLocal 的内存泄漏问题
ThreadLocal使用不当会导致内存泄漏,主要原因如下:ThreadLocalMap的键是弱引用(WeakReference),但值是强引用。- 如果
ThreadLocal实例被回收,但线程仍然存活,ThreadLocalMap中的值不会被回收,从而导致内存泄漏。
- 使用完
ThreadLocal后,调用remove()方法清除线程本地变量。

浙公网安备 33010602011771号