HttpSession 的运行原理

HttpSession 的运行原理(基于 Java Web)

HttpSession 是 Java Web 开发中用于在服务器端存储用户会话数据的机制,它的核心作用是跟踪用户状态(如登录信息、购物车数据等)。


1. HttpSession 的基本概念

  • 会话(Session):指用户从访问网站到关闭浏览器(或超时)期间的一系列交互过程。

  • Session ID服务器为每个会话分配的唯一标识符(通常是一个 JSESSIONID Cookie)

  • 存储位置:Session 数据默认存储在 服务器内存 中(Tomcat/Jetty等),也可以配置到 Redis、数据库等。


2. HttpSession 的工作流程

(1)创建 Session

当客户端(浏览器)第一次访问服务器时:

  1. 服务器检查请求是否携带 JSESSIONID Cookie。

  2. 如果没有,则创建一个新的 Session,并生成唯一的 JSESSIONID

  3. 服务器在响应头中返回 Set-Cookie: JSESSIONID=xxx,浏览器保存该 Cookie。

(2)后续请求携带 Session ID

浏览器在后续请求中会自动带上 JSESSIONID Cookie:

GET /home HTTP/1.1
Cookie: JSESSIONID=abc123

服务器根据 JSESSIONID 找到对应的 Session,并读取/写入数据。

(3)相关配置

        在一些前后端分离的项目中,涉及跨域问题,这时如果想让会话携带Cookie等凭证,那么需要配置: withCredentials: true。withCredentials可以控制请求是否携带Cookie等凭证,同样的后端也需要设置。

         前端代码实例:

fetch('http://api.example.com/login', {
  method: 'POST',
  credentials: 'include', // 等效于 withCredentials: true
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ username: 'user', password: 'pass' })
});

       后端代码:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: <具体域名>  

注意前后端都需要配置,否则也会报错

(3)Session 失效

Session 会在以下情况被销毁:

  • 超时session.setMaxInactiveInterval(1800)(30分钟无活动则失效)。

  • 主动销毁:调用 session.invalidate()

  • 服务器重启(如果 Session 未持久化到外部存储)。


3. HttpSession 的核心 API

方法说明
request.getSession()获取 Session(如果没有则创建)
request.getSession(false)获取 Session(如果没有则返回 null
session.getId()获取 Session ID
session.setAttribute("key", value)存储数据
session.getAttribute("key")读取数据
session.removeAttribute("key")删除数据
session.invalidate()销毁 Session
session.setMaxInactiveInterval(seconds)设置超时时间(秒)

4. HttpSession 的底层实现

(1)Session 存储方式

  • 默认:存储在 服务器内存(Tomcat 使用 ConcurrentHashMap)。

  • 分布式环境:使用 Redis数据库 或 Session 复制(如 Spring Session)。

(2)Session ID 的传递方式

  • Cookie(默认)

    Set-Cookie: JSESSIONID=abc123; Path=/; HttpOnly
  • URL 重写(禁用 Cookie 时):

    <a href="/home;jsessionid=abc123">Home</a>

5. 代码示例

(1)存储 Session 数据

@GetMapping("/login")
public String login(HttpServletRequest request) {
    HttpSession session = request.getSession(); // 获取或创建 Session
    session.setAttribute("user", "张三"); // 存储数据
    session.setMaxInactiveInterval(1800); // 设置30分钟超时
    return "登录成功";
}

(2)读取 Session 数据

@GetMapping("/profile")
public String profile(HttpServletRequest request) {
    HttpSession session = request.getSession(false); // 不自动创建 Session
    if (session == null) {
        return "未登录";
    }
    String user = (String) session.getAttribute("user");
    return "当前用户: " + user;
}

(3)销毁 Session(退出登录)

@GetMapping("/logout")
public String logout(HttpServletRequest request) {
    HttpSession session = request.getSession(false);
    if (session != null) {
        session.invalidate(); // 销毁 Session
    }
    return "已退出登录";
}

6. 常见问题

(1)Session 和 Cookie 的区别

SessionCookie
存储位置服务器浏览器
安全性较高(数据在服务端)较低(可能被篡改)
存储大小较大(依赖服务器内存)较小(一般 ≤4KB)
生命周期可设置超时时间可设置过期时间

(2)如何防止 Session 劫持?

  • 使用 HTTPS 加密传输 JSESSIONID

  • 设置 HttpOnly 和 Secure 标志,防止 XSS 攻击:

    // Spring Boot 配置(application.properties)
    server.servlet.session.cookie.http-only=true
    server.servlet.session.cookie.secure=true

7. 总结

  1. HttpSession 用于在服务器端存储用户会话数据,依赖 JSESSIONID 标识用户。

  2. 默认存储在内存,分布式环境可用 Redis 共享 Session。

  3. 核心操作setAttribute()getAttribute()invalidate()

  4. 安全建议:使用 HttpOnly + Secure Cookie,避免 Session 劫持。

### Servlet 运行原理详解 #### 1. Servlet 的生命周期管理 Servlet 生命周期由容器控制,主要分为三个阶段:加载与实例化、初始化、服务以及销毁。 - **加载与实例化** 当第一次请求到达时,Web 容器会创建一个新的 Servlet 实例[^2]。对于大多数情况而言,在整个应用程序运行期间只会存在一个 Servlet 实例来处理来自多个客户端的并发请求。 - **初始化** 一旦被实例化之后,`init()` 方法会被调用一次用于完成一些必要的准备工作,比如读取配置文件中的参数等操作。此过程通过 `ServletConfig` 对象传递给 servlet 特定的信息集合[K-V键值对][^4]。 - **服务** 每当接收到新的 HTTP 请求时,都会触发相应的 service() 函数执行具体的业务逻辑;而在这个过程中如果涉及到数据存储,则可以利用 HttpSession 来保存用户的临时状态信息以便后续交互使用[^1]。 - **销毁** 在 Web 应用程序即将停止前,容器将会调用 destroy() 方法释放资源并清理环境,确保所有未完成的任务都能妥善结束[^3]。 #### 2. 多用户环境下 Session 和 Context 的作用范围 针对多位访客同时访问同一页面的情况: - 每位客户都有自己独立的 session 变量副本,这意味着即使两个以上的人在同一时间浏览相同的网页也不会相互干扰到对方的数据; - 而关于上下文 (context),它在整个应用级别内有效,因此可以在不同 servlet 或者 jsp 页面间共享公共属性或对象实例而不必担心冲突问题。 具体来说,服务器端是依靠 cookie 中携带唯一标识符(通常是 JSESSIONID)的方式来进行身份验证和跟踪各个会话之间的区别所在。 ```java // 获取当前用户的Session对象 HttpSession session = request.getSession(); session.setAttribute("username", "John Doe"); String username = (String) session.getAttribute("username"); // 访问全局的应用级ServletContext ServletContext context = getServletContext(); context.setAttribute("appWideProperty", value); Object appValue = context.getAttribute("appWideProperty"); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

撸猫791

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值