从 01 开始 从 01 开始
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档
  • JavaSE

  • JavaSenior

  • JavaEE

  • JavaWeb

    • 服务器软件

    • 环境管理和配置管理-科普篇
    • Servlet入门

      • 什么是 Servlet
      • Servlet 入门案例
      • Servlet 生命周期
      • Servlet 中的注解
      • Tomcat 集成 IDEA
      • Servlet 体系结构
      • HTTP 协议基础
      • 深入 request 和 response 对象
      • request 对象基本使用
      • request 其他功能
      • Servlet 实现登录功能
      • HTTP 协议基础-响应
      • Response 对象基本使用
      • response 对象之重定向
      • response 输出字符到浏览器
      • response 输出字节数据
      • 验证码案例
      • ServletContext
      • 文件下载案例
      • Cookie 笔记
      • Cookie 的更多细节
      • Cookie 实践:记住上次访问时间
      • JSP 入门
      • JSP 的内置对象和案例
      • IDEA 与 JavaWeb 的小技巧
      • Session 笔记
        • Session 入门
        • Session 原理
        • Session 的细节
        • session 的特点
      • 验证码案例
      • JSP 深入学习
      • MVC 开发模式
      • EL 表达式和 JSTL 标签
      • JSTL 标签库
      • 案例:列表的增删改查
      • Filter 学习
      • Filter 案例
      • Listener 学习
      • Java 中的 Ajax
      • Java 中的 JSON
  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

  • Java
  • JavaWeb
  • Servlet入门
2023-04-17
目录

Session 笔记

# 100.Session 笔记

概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象 HttpSession 中。

‍

# Session 入门

之前我们说过 request 是域对象,可以共享数据,ServletContext 也是域对象,可以共享数据;同理,HttpSession 也是一个域对象,也有如下方法,用来共享数据:

  1. setAttribute(String name,Object value)

  2. getAttribute(String name)

  3. removeAttribute(String name) ‍ 使用 Session 共享数据,步骤也很简单:

  4. 获取 HttpSession 对象: HttpSession session = request.getSession();

  5. 使用 HttpSession 对象:调用 setAttribute,getAttribute 等方法 ‍ 我们写两个 Servlet 来验证下:

package com.peterjxl.session;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebServlet("/sessionDemo1")
public class SessionDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        session.setAttribute("msg", "Hello Session!");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

‍

package com.peterjxl.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/sessionDemo2")
public class SessionDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        Object msg = session.getAttribute("msg");
        System.out.println(msg);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

‍ 重启 Tomcat,访问 http://localhost: 8080/hello/sessionDemo1,

然后访问 http://localhost: 8080/hello/sessionDemo2,可以看到后台打印了 Hello Session!。 ‍ 关闭浏览器,会话就结束了,再次访问 sessionDemo2,发现打印了 null。也就是说,在一次会话中才能使用 Session,关闭浏览器就断掉了会话

# Session 原理

访问多个 Servlet,服务器是如何确保在一次会话范围内,多次获取的 Session 对象是同一个?Session 的实现是依赖于 Cookie 的

  1. 当我们第一次访问 Servlet 时,也就会第一次获取 Session,服务器会创建一个 Session 对象,并且这个对象有一个唯一的 ID,假设 ID = 123456
  2. 返回响应消息给数据的时候,会设置 Cookie,Cookie 的名字为 JSESSIONID,值为 Session 的 ID。
  3. 浏览器会保存这个 Cookie,并且下次访问 Servlet 的时候,会带上 Cookie
  4. 服务器再次收到请求的时候,当我们获取 Session 对象的时候,服务器会根据 Session 的 ID 查找内存中有没对应的 Session 对象,有则返回 HttpSession session = req.getSession();

我们可以来验证下。关闭浏览器,然后打开控制台,访问 SessionDemo1,可以看到服务器有设置 Cookie:

‍

注:如果不想关闭浏览器,可以通过控制台删除 Cookie,也可以实现清空的效果。

然后我们访问 SessionDemo2 的时候,会带上这个 Session 的 ID。

# Session 的细节

这里有几个小问题要确认:

  • 当客户端关闭后,服务器不关闭,两次获取 session 是否为同一个?
  • 客户端不关闭,服务器关闭后,两次获取的 session 是同一个吗?
  • session 的失效时间? ‍

# 客户端关闭

当客户端关闭后,服务器不关闭,两次获取 session 是否为同一个?

默认情况下,不是。客户端关闭后,认为会话关闭了。 ‍ 实践:访问 Servlet 后,打印对象;然后关闭浏览器,再次访问,打印的对象和前一次不同。

HttpSession session = req.getSession();
System.out.println(session);
1
2

‍ 如果需要相同,则可以创建 Cookie, 键为 JSESSIONID,值就是 Session 的 ID,容纳后设置最大存活时间,让 cookie 持久化保存:

Cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60 * 60);
resp.addCookie(c);
1
2
3

全部代码:

package com.peterjxl.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/sessionDemo3")
public class SessionDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        System.out.println(session);
        Cookie c = new Cookie("JSESSIONID",session.getId());
        c.setMaxAge(60 * 60);
        resp.addCookie(c);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 服务器关闭

客户端不关闭,服务器关闭后,两次获取的 session 是同一个吗?不是同一个,因为创建对象有一定的随机性(随机分配内存)。我们可以验证下,新写一个 Servlet:

package com.peterjxl.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/sessionDemo4")
public class SessionDemo4 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        System.out.println(session);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

‍ 重启 Tomcat,访问 http://localhost: 8080/hello/sessionDemo4,可以看到打印:

org.apache.catalina.session.StandardSessionFacade@6ca699f9
1

‍ 再次重启 Tomcat,访问,输出:很明显和之前的输出不一样

org.apache.catalina.session.StandardSessionFacade@5f59f4fe
1

如果不一样,有什么问题呢?比如我在某东,未登录,加了几个商品到购物车,这些数据是存储到 Session 里的;准备结算的时候接到了一个电话,打了 4 分钟,在这 4 分钟内,某东重启了一次,导致我购物车里的商品丢失了,非常影响体验,我可能就不买或者少买了东西,损失了流量。

因此我们得考虑保存下数据。这就涉及到如下概念:

  • session 的钝化:在服务器正常关闭之前,将 session 对象系列化到硬盘上
  • session 的活化:在服务器启动后,将 session 文件转化为内存中的 session 对象即可。

Tomcat 能自动完成以上工作

# Session 钝化、活化实验

实践:在 IDEA 中不能实现 Session 的钝化和活化,得用本地 Tomcat 才能完成。

演示步骤:

一、先停止 IDEA 里启动的 Tomcat ‍ 二、将我们的所有项目文件打成一个压缩包,然后改名为 hello.war

注意点:由于笔者之前在 img 目录下放了一个中文名的图片,导致启动的时候报错 java.lang.IllegalArgumentException: MALFORMED
at java.util.zip.ZipCoder.toString(ZipCoder.java: 58)
at java.util.zip.ZipFile.getZipEntry(ZipFile.java: 566)
at java.util.zip.ZipFile.access$900(ZipFile.java: 60)

windows 环境下,默认字符集为 GBK,ZipFile 默认使用 UTF-8 字符集,当文件名存在中文时,处理时就会报错。笔者暂未找到解决方案,因此先删除了下中文名的图片

启动 Tomcat,访问路径 http://localhost: 8080/hello/sessionDemo1;

然后再访问 http://localhost: 8080/hello/sessionDemo2,可以看到 Tomcat 的黑窗口里打印了 Hello Session

查看 Tomcat 的 work 目录,一步步定义到我们的项目目录里,可以看到是空的:

‍

正常关闭 Tomcat:点击 Tomcat 的 bin 目录下的 shutdown.bat。

发现 work 目录有了 SESSIONS.ser 文件:

重新启动服务器,该 SESSIONS.ser 文件会被自动读取,然后被删除;

再次访问 http://localhost: 8080/hello/sessionDemo2,同样打印了 msg 的值。 ‍ 为什么在 IDEA 里不能完成 Session 的钝化和活化?因为 IDEA 关闭服务后,虽然会钝化(可以在 work 目录里看到 SESSIONS.ser 文件),但是在重启服务器时,会将 work 目录删除后再新建,所以活化生效了,因为 IDEA 里不能生效。

# Session 有效期

Session 什么时候会被销毁?

  1. 服务器关闭
  2. session 对象调用 invalidate() 方法。 ‍ 那如果不主动销毁,Session 会一直保持在内存里吗?不是的,session 默认失效时间 30 分钟。我们可以看 Tomcat 的配置文件 apache-tomcat-9.0.73\conf\web.xml,637 行左右:
  <!-- ==================== Default Session Configuration ================= -->
  <!-- You can set the default session timeout (in minutes) for all newly   -->
  <!-- created sessions by modifying the value below.                       -->

    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
1
2
3
4
5
6
7

通过注释我们可以知道,我们可以修改这个配置,数值是以分钟为单位。 ‍ 这个配置文件是所有项目的父配置文件,不建议修改,这样可能会影响所有项目的配置;建议在自己的项目的 web.xml 文件里修改。

# session 的特点

  • session 用于存储一次会话的多次请求的数据,存在服务器端
  • session 可以存储任意类型,任意大小的数据(只要内存够) ‍ session 与 Cookie 的区别:
  1. session 存储数据在服务器端,Cookie 在客户端
  2. session 没有数据大小限制,Cookie 有(Session 有主菜的意思,而 Cookie 是小饼干,谁大谁小一听便知)
  3. session 数据安全一点,Cookie 相对于不安全 ‍
上次更新: 2025/5/17 12:26:09
IDEA 与 JavaWeb 的小技巧
验证码案例

← IDEA 与 JavaWeb 的小技巧 验证码案例→

最近更新
01
吐槽一下《僵尸校园》
05-15
02
2025 年 4 月记
04-30
03
山西大同 “订婚强奸案” 将会给整个社会带来的影响有多严重? - 知乎 转载
04-26
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式