会话和域

会话和域

  • 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的使用

    • 设置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 的主要作用是:
    • 线程隔离:为每个线程提供一个独立的变量副本,避免线程间共享变量。
    • 简化线程安全:通过线程隔离,避免了使用同步机制(如 synchronizedLock)来保证线程安全。
    • 传递上下文信息:在复杂的多线程场景中,可以通过 ThreadLocal 传递上下文信息(如用户会话、事务信息等)。
  • ThreadLocal 的核心方法是:
    • set(T value):设置当前线程的变量副本。
    • get():获取当前线程的变量副本。
    • remove():移除当前线程的变量副本。

ThreadLocal 的典型应用场景:

  • 数据库连接管理

    • 在数据库连接池中,可以使用 ThreadLocal 为每个线程分配一个独立的数据库连接,避免线程间共享连接。
  • 用户会话管理

    • 在 Web 应用中,可以使用 ThreadLocal 存储当前用户的会话信息(如用户 ID、权限等)。
  • 事务管理

    • 在事务管理中,可以使用 ThreadLocal 传递事务上下文信息。
  • 日期格式化

    • SimpleDateFormat 是线程不安全的,可以使用 ThreadLocal 为每个线程分配一个独立的 SimpleDateFormat 实例。

ThreadLocal 的内存泄漏问题

  • ThreadLocal 使用不当会导致内存泄漏,主要原因如下:
    • ThreadLocalMap 的键是弱引用(WeakReference),但值是强引用。
    • 如果 ThreadLocal 实例被回收,但线程仍然存活,ThreadLocalMap 中的值不会被回收,从而导致内存泄漏。
  • 使用完 ThreadLocal 后,调用 remove() 方法清除线程本地变量。
posted @ 2025-03-18 15:24  QAQ001  阅读(27)  评论(0)    收藏  举报