从01开始 从01开始
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)

peterjxl

人生如逆旅,我亦是行人
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)
  • 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
      • Servlet
    • JavaWeb
  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

  • Java并发

  • Java源码

  • JVM

  • 韩顺平

  • Java
  • 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共享数据,步骤也很简单:

  1. 获取HttpSession对象: HttpSession session = request.getSession();​
  2. 使用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相对于不安全

‍

‍

‍

‍

在GitHub上编辑此页 (opens new window)
上次更新: 2023/5/6 21:54:08
IDEA与JavaWeb的小技巧
验证码案例

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

Theme by Vdoing | Copyright © 2022-2023 粤ICP备2022067627号-1 粤公网安备 44011302003646号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式