• 会话技术之Coookie && Session详解


    会话跟踪技术的概述

    会话: 用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应

    1. 从浏览器发出请求到服务端响应数据给前端之后,一次会话(在浏览器和服务器之间)就被建立了
    2. 会话被建立后,如果浏览器或服务端都没有被关闭,则会话就会持续建立着
    3. 浏览器和服务器就可以继续使用该会话进行请求发送和响应,上述的整个过程就被称之为会话

    用实际场景来理解下会话,比如在我们访问京东的时候,当打开浏览器进入京东首页后,浏览器和京东的服务器之间就建立了一次会话,后面的搜索商品,查看商品的详情,加入购物车等都是在这一次会话中完成。

    思考:下图中总共建立了几个会话?

    • 每个浏览器都会与服务端建立了一个会话,加起来总共是3个会话
      在这里插入图片描述

    会话跟踪: 一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据

    • 服务器会收到多个请求,这多个请求可能来自多个浏览器,如上图中的6个请求来自3个浏览器
    • 服务器需要用来识别请求是否来自同一个浏览器
    • 服务器用来识别浏览器的过程,这个过程就是会话跟踪
    • 服务器识别浏览器后就可以在同一个会话中多次请求之间来共享数据

    我们需要思考:为什么现在浏览器和服务器不支持数据共享呢?

    • 浏览器 和 服务器之间使用的是 HTTP 请求来进行数据传输。
    • HTTP协议是无状态的,每次浏览器向服务器请求时,服务器都会将该请求视为新的请求
    • HTTP协议设计成无状态的目的是让每次请求之间相互独立,互不影响
    • 请求与请求之间独立后,就无法实现多次请求之间的数据共享。

    那么该如何实现会话跟踪技术呢? 具体的实现方式有:

    1. 客户端会话跟踪技术:Cookie
    2. 服务端会话跟踪技术:Session

    这两个技术都可以实现会话跟踪,它们之间最大的区别:Cookie是存储在浏览器端而Session是存储在服务器端

    Cookie

    Cookie的基本使用

    Cookie:客户端会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问。

    Cookie的工作流程
    在这里插入图片描述Cookie的基本使用

    对于Cookie的操作主要分两大类,本别是发送Cookie获取Cookie

    1. 发送Cookie

    // 1. 创建Cookie对象,并设置数据
    Cookie cookie = new Cookie("key","value");
    
    // 2. 发送Cookie到客户端:使用==response==对象
    response.addCookie(cookie);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2. 获取Cookie

    // 1. 获取客户端携带的所有Cookie,使用==request==对象
    Cookie[] cookies = request.getCookies();
    
    
    // 遍历数组,获取每一个Cookie对象:forEach
    // 使用Cookie对象方法获取数据
    
    cookie.getName();
    cookie.getValue();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    测试案例完成Cookie的发送和接收,具体实现步骤如下:

    • 编写一个名称为AServlet的Servlet类, 在AServlet中创建Cookie对象, 存入数据,发送给前端。

      package cookie;
       /**
       * @Author Mr.Lu
       * @Date 2022/7/29 9:48
       * @ClassName AServlet
       * @Version 1.0
       */
      
      import javax.servlet.*;
      import javax.servlet.annotation.*;
      import javax.servlet.http.*;
      import java.io.*;
      import java.net.URLEncoder;
      
      @WebServlet(urlPatterns = "/aServlet")
      public class AServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // 发送Cookie
              // 1. 创建Cookie对象
              Cookie cookie = new Cookie("username", "zs");
              
              // 2. 发送Cookie
              response.addCookie(cookie);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
    • 启动测试,在浏览器查看Cookie对象中的值, 访问http://localhost:8080/cookie-demo/aServlet
      在这里插入图片描述在这里插入图片描述

    • 编写一个名称为BServlet的Servlet类, BServlet中使用request对象获取Cookie数组,遍历数组,从数据中获取指定名称对应的值。

      package cookie;
       /**
       * @Author Mr.Lu
       * @Date 2022/7/29 10:00
       * @ClassName BServlet
       * @Version 1.0
       */
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      
      @WebServlet(urlPatterns = "/bServlet")
      public class BServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // 1. 获取Cookie
              Cookie[] cookies = request.getCookies();
              // 2. 遍历所有Cookie
              for(Cookie cookie : cookies){
                  String key = cookie.getName();
                  if("username".equals(key)){
                      String value = cookie.getValue();
                      System.out.println(key + " : " + value);
                  }
              }
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
    • 启动测试,在控制台打印出获取的值, 访问http://localhost:8080/cookie-demo/bServlet
      在这里插入图片描述在这里插入图片描述

    小结

    • 发送Cookie:
      • 创建Cookie对象,并设置值:Cookie cookie = new Cookie(“key”,“value”);
      • 发送Cookie到客户端使用的是Reponse对象:response.addCookie(cookie);
    • 获取Cookie:
      • 使用Request对象获取Cookie数组:Cookie[] cookies = request.getCookies();
      • 遍历数组;
      • 获取数组中每个Cookie对象的值:cookie.getName() 和 cookie.getValue();

    Cookie的原理分析

    对于Cookie的实现原理是 基于HTTP协议的, 其中设计到HTTP协议中的两个请求头信息:

    • 响应头: set-cookie
    • 请求头: cookie
      在这里插入图片描述

    现在我们使用上述的测试案例进行验证:

    • 访问AServlet对应的地址http://localhost:8080/cookie-demo/aServlet, 使用 Google Chrom 浏览器打开开发者工具(F12或Crtl+Shift+I)进行查看响应头中的数据

      在这里插入图片描述

    • 访问BServlet对应的地址http://localhost:8080/cookie-demo/bServlet, 使用 Google Chrom 浏览器打开开发者工具(F12或Crtl+Shift+I)进行查看请求头中的数据
      在这里插入图片描述

    Cookie的使用细节

    Cookie的存活时间

    // 设置Cookie存活时间
    setMaxAge(int seconds)
    
    • 1
    • 2

    参数值为:

    1. 正数:将Cookie写入浏览器所在电脑的硬盘,持久化存储。到时间自动删除
    2. 负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则Cookie被销毁
    3. 零:删除对应Cookie
    • 我们在AServlet中去设置Cookie的存活时间。

      package cookie; 
      /**
       * @Author Mr.Lu
       * @Date 2022/7/29 9:48
       * @ClassName AServlet
       * @Version 1.0
       */
      
      import javax.servlet.*;
      import javax.servlet.annotation.*;
      import javax.servlet.http.*;
      import java.io.*;
      import java.net.URLEncoder;
      
      @WebServlet(urlPatterns = "/aServlet")
      public class AServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // 发送Cookie
              // 1. 创建Cookie对象
              Cookie cookie = new Cookie("username", "zs");
              // 设置存货时间, 1周7天, 以秒为单位
              cookie.setMaxAge(7 * 24 * 60 * 60);  // 易阅读,需程序计算
              // cookie.setMaxAge(604800); //不易阅读(可以使用注解弥补),程序少进行一次计算
      
              // 2. 发送Cookie
              response.addCookie(cookie);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35

    修改完代码后,启动测试,访问http://localhost:8080/cookie-demo/aServlet

    • 通过浏览器查看Cookie的内容,会发现Cookie的相关信息
      在这里插入图片描述
    • 访问一个AServlet后,把浏览器关闭重启后,再去访问http://localhost:8080/cookie-demo/bServet,能在控制台打印出username:zs,说明Cookie没有随着浏览器关闭而被销毁.
      在这里插入图片描述

    Cookie存储中文

    抛出问题

    • 我们把AServlet类中的 username=zs 的值改成 username=张三,把汉字张三存入到Cookie中:
      package cookie; /**
      * @Author Mr.Lu
      * @Date 2022/7/29 9:48
      * @ClassName AServlet
      * @Version 1.0
      */
      
      import javax.servlet.*;
      import javax.servlet.annotation.*;
      import javax.servlet.http.*;
      import java.io.*;
      import java.net.URLEncoder;
      
      @WebServlet(urlPatterns = "/aServlet")
      public class AServlet extends HttpServlet {
         @Override
         protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
             // 发送Cookie
             // 1. 创建Cookie对象
             Cookie cookie = new Cookie("username", "张三");
             // 设置存货时间, 1周7天, 以秒为单位
             cookie.setMaxAge(7 * 24 * 60 * 60);  // 易阅读,需程序计算
             // cookie.setMaxAge(604800); //不易阅读(可以使用注解弥补),程序少进行一次计算
      
             // 2. 发送Cookie
             response.addCookie(cookie);
         }
      
         @Override
         protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
             this.doGet(request, response);
         }
      }
      
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35

    • 启动访问测试,访问http://localhost:8080/cookie-demo/aServlet会发现浏览器会提示错误信息: Control character in cookie value or attribute.
      在这里插入图片描述

    得出结论:

    • Cookie不能直接存储中文

    解决方式:URL编码, 想要仔细了解URL编码可以参考文章:https://blog.csdn.net/qq_43751200/article/details/125357013 中的 请求参数中文乱码问题模块 中的 GET请求解决方案。

    下面是一个通过URL编码解决中文存储问题的实例:

    • 在AServlet中对中文进行URL编码,采用URLEncoder.encode(),将编码后的值存入Cookie中:

      package cookie; /**
       * @Author Mr.Lu
       * @Date 2022/7/29 9:48
       * @ClassName AServlet
       * @Version 1.0
       */
      
      import javax.servlet.*;
      import javax.servlet.annotation.*;
      import javax.servlet.http.*;
      import java.io.*;
      import java.net.URLEncoder;
      
      @WebServlet(urlPatterns = "/aServlet")
      public class AServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // 发送Cookie
              // 1. 创建Cookie对象
              String value = "张三";
              value = URLEncoder.encode(value, "UTF-8"); // 对中文进行URL编码
              System.out.println("存储数据value : " + value);
              Cookie cookie = new Cookie("username", value);
              // 设置存货时间, 1周7天, 以秒为单位
              cookie.setMaxAge(7 * 24 * 60 * 60);  // 易阅读,需程序计算
              
              // 2. 发送Cookie
              response.addCookie(cookie);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
    • 在BServlet中获取Cookie中的值, 获取的值为URL编码后的值, 将获取的值在进行URL解码,采用URLDecoder.decode(),就可以获取到对应的中文值:

      package cookie; /**
       * @Author Mr.Lu
       * @Date 2022/7/29 10:00
       * @ClassName BServlet
       * @Version 1.0
       */
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      import java.net.URLDecoder;
      
      @WebServlet(urlPatterns = "/bServlet")
      public class BServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // 1. 获取Cookie
              Cookie[] cookies = request.getCookies();
              // 2. 遍历所有Cookie
              for(Cookie cookie : cookies){
                  String key = cookie.getName();
                  if("username".equals(key)){
                      String value = cookie.getValue();  // 获取的是URL编码后的值 %E5%BC%A0%E4%B8%89
                      value = URLDecoder.decode(value, "UTF-8");  // value解码后为 张三
                      System.out.println(key + " : " + value);
                      break;
                  }
              }
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36

    • 分别访问http://localhost:8080/cookie-demo/aServlethttp://localhost:8080/cookie-demo/bServlet 查看控制台打印结果:
      在这里插入图片描述在这里插入图片描述

    小结

    Cookie的使用细节中,讲了Cookie的存活时间存储中文:

    • 存活时间,使用 setMaxAage() 进行设置
    • 存储中文,使用 URL 编码和解码

    Session

    Session:服务端会话跟踪技术:将数据保存到服务端。

    • Session是存储在服务端而Cookie是存储在客户端
    • 存储在客户端的数据容易被窃取和截获,存在很多不安全的因素
    • 存储在服务端的数据相比于客户端来说就更安全

    Session的工作流程
    在这里插入图片描述

    • 在服务端的AServlet获取一个Session对象,把数据存入其中
    • 在服务端的BServlet获取到相同的Session对象,从中取出数据
    • 就可以实现一次会话中多次请求之间的数据共享了
    • 问题提出 ?? 如何保证AServlet和BServlet使用的是同一个Session对象(在原理分析会有介绍)?

    Session的基本使用

    在JavaEE中提供了HttpSession接口,来实现一次会话的多次请求之间数据共享功能。

    具体的使用步骤为:
    
    // 获取Session对象,使用的是request对象
    HttpSession session = request.getSession();
    
    // Session对象提供的功能:
    // 1. 存储数据到 session 域中
    void setAttribute(String name, Object o)
    
    // 2. 根据 key,获取值
    Object getAttribute(String name)
    
    // 3. 根据 key,删除该键值对
    void removeAttribute(String name)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    下面通过一个案例完成对Session的使用,具体实现步骤为

    • 创建名为SessionServlet1的Servlet类, 功能:获取Session对象、存储数据

      	package session; /**
       * @Author Mr.Lu
       * @Date 2022/7/30 12:25
       * @ClassName SessionServlet1
       * @Version 1.0
       */
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      
      @WebServlet(urlPatterns = "/demo1")
      public class SessionServlet1 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // 存储到Session中
              // 1. 获取Session对象
              HttpSession session = request.getSession();
              // 2. 存储数据
              session.setAttribute("username", "zs");
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
    • 创建名为SessionServlet2的Servlet类,功能: 获取Session对象、获取数据

      package session; /**
       * @Author Mr.Lu
       * @Date 2022/7/30 12:25
       * @ClassName SessionServlet2
       * @Version 1.0
       */
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      
      @WebServlet(urlPatterns = "/demo2")
      public class SessionServlet2 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // 从Session中获取数据
              // 1. 获取session对象
              HttpSession session = request.getSession();
              // 2. 获取数据
              Object username = session.getAttribute("username");
              System.out.println(username);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
    • 启动测试,

      • 先访问http://localhost:8080/cookie-demo/demo1, 将数据存入Session
      • 在访问http://localhost:8080/cookie-demo/demo2, 从Session中获取数据
      • 查看控制台
        在这里插入图片描述

    通过案例的效果,能看到Session是能够在一次会话中两次请求之间共享数据。

    Session的原理分析

    • Session是基于Cookie实现的
      在这里插入图片描述Session要想实现一次会话多次请求之间的数据共享,就必须要保证多次请求获取Session的对象是同一个

    测试一次会话中获取的Session对象是同一个

    • SessionServlet1

      	package session; /**
       * @Author Mr.Lu
       * @Date 2022/7/30 12:25
       * @ClassName SessionServlet1
       * @Version 1.0
       */
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      
      @WebServlet(urlPatterns = "/demo1")
      public class SessionServlet1 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // 存储到Session中
              // 1. 获取Session对象
              HttpSession session = request.getSession();
              System.out.println(session);
              // 2. 存储数据
              session.setAttribute("username", "zs");
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
    • SessionServlet2

      package session; /**
       * @Author Mr.Lu
       * @Date 2022/7/30 12:25
       * @ClassName SessionServlet2
       * @Version 1.0
       */
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      
      @WebServlet(urlPatterns = "/demo2")
      public class SessionServlet2 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // 从Session中获取数据
              // 1. 获取session对象
              HttpSession session = request.getSession();
               System.out.println(session);
              // 2. 获取数据
              Object username = session.getAttribute("username");
              // System.out.println(username);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
    • 启动测试,分别访问http://localhost:8080/cookie-demo/demo1http://localhost:8080/cookie-demo/demo2
      在这里插入图片描述

    提问: Session是如何保证在一次会话中获取的Session对象是同一个呢?
    在这里插入图片描述

    1. demo1在第一次获取session对象的时候,session对象会有一个唯一的标识,假如是id:10

    2. demo1在session中存入其他数据并处理完成所有业务后,需要通过Tomcat服务器响应结果给浏览器

    3. Tomcat服务器发现业务处理中使用了session对象,就会把session的唯一标识id:10当做一个cookie,添加Set-Cookie:JESSIONID=10到响应头中,并响应给浏览器

    4. 浏览器接收到响应结果后,会把响应头中的cookie数据存储到浏览器的内存中

    5. 浏览器在同一会话中访问demo2的时候,会把cookie中的数据按照cookie: JESSIONID=10的格式添加到请求头中并发送给服务器Tomcat

    6. demo2获取到请求后,从请求头中就读取cookie中的JSESSIONID值为10,然后就会到服务器内存中寻找id:10的session对象,如果找到了,就直接返回该对象,如果没有则新创建一个session对象

    7. 关闭打开浏览器后,因为浏览器的cookie已被销毁,所以就没有JESSIONID的数据,服务端获取到的session就是一个全新的session对象

    接下来通过实例进行演示:

    (1) 使用Google chrome浏览器访问http://localhost:8080/cookie-demo/demo1,打开开发者模式(F12或Ctrl+Shift+I),查看==响应头(Response Headers)数据:
    在这里插入图片描述
    (2) 使用Google chrome浏览器再次访问http://localhost:8080/cookie-demo/demo2,查看
    请求头(Request Headers)==数据:
    在这里插入图片描述

    Session的使用细节

    Session钝化与活化

    问题抛出:服务器正常重启后,Session中的数据是否还在?????

    下面来进行测试:

    1. 启动:进入到项目pom.xml所在目录,执行tomcat7:run
      在这里插入图片描述

    2. 停止:在启动的命令行界面,输入ctrl+c
      在这里插入图片描述

    有了上述两个正常启动和关闭的方式后,接下来的测试流程是:
    (1) 先启动Tomcat服务器

    (2) 访问http://localhost:8080/cookie-demo/demo1将数据存入session中

    (3) 正确停止Tomcat服务器, 会在这个目录下生成一个SESSIONS.ser文件
    在这里插入图片描述
    (4) 再次重新启动Tomcat服务器, 这个目录下的SESSIONS.ser文件自动消失了
    在这里插入图片描述
    (5) 访问http://localhost:8080/cookie-demo/demo2 查看是否能获取到session中的数据
    在这里插入图片描述

    经过测试,会发现只要服务器是正常关闭和启动,session中的数据是可以被保存下来的。

    那么Tomcat服务器到底是如何做到的呢?

    具体的原因就是: Session的钝化和活化:

    • 钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘的文件中
      • 钝化的数据路径为:项目目录\target\tomcat\work\Tomcat\localhost\项目名称\SESSIONS.ser
        在这里插入图片描述
    • 活化:再次启动服务器后,从文件中加载数据到Session中
      • 数据加载到Session中后,路径中的SESSIONS.ser文件会被删除掉
        在这里插入图片描述

    Session销毁

    session的销毁会有两种方式:

    • 默认情况下,无操作,30分钟自动销毁
      • 对于这个失效时间,是可以通过配置进行修改的
        • 在项目的web.xml中配置
    
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
    
        <session-config>
            <session-timeout>100session-timeout>
        session-config>
    
    web-app>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 调用Session对象的invalidate()进行销毁

      • 在SessionServlet2类中添加session销毁的方法
    package session;
        /**
     * @Author Mr.Lu
     * @Date 2022/7/30 12:25
     * @ClassName SessionServlet2
     * @Version 1.0
     */
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    
    @WebServlet(urlPatterns = "/demo2")
    public class SessionServlet2 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 从Session中获取数据
            // 1. 获取session对象
            HttpSession session = request.getSession();
            System.out.println(session);
            
            // 销毁
            session.invalidate();
            
            
            // 2. 获取数据
            Object username = session.getAttribute("username");
    //        System.out.println(username);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 启动访问测试,先访问demo1将数据存入到session,再次访问demo2从session中获取数据
      在这里插入图片描述

    • 该销毁方法一般会在用户退出的时候,需要将session销毁掉。

    Cookie与Session对比分析

    • Cookie 和 Session 都是来完成一次会话内多次请求间数据共享的。

    Cookie和Session的区别是什么?

    • 区别:
      • 存储位置:Cookie 是将数据存储在客户端,Session 将数据存储在服务端
      • 安全性:Cookie不安全,Session安全
      • 数据大小:Cookie最大3KB,Session无大小限制
      • 存储时间:Cookie可以通过setMaxAge()长期存储,Session默认30分钟
      • 服务器性能:Cookie不占服务器资源,Session占用服务器资源

    Cookie和Session的应用场景分别是什么?

    • 应用场景:
      • 购物车:使用Cookie来存储
      • 以登录用户的名称展示:使用Session来存储
      • 记住我功能:使用Cookie来存储
      • 验证码:使用session来存储

    结论

    • Cookie是用来保证用户在未登录情况下的身份识别
    • Session是用来保存用户登录后的数据
  • 相关阅读:
    UGUI 判断鼠标是否在UI上面
    漫谈计算机网络:物理层 ----- 双绞线&光纤?,从最底层开始了解计算机网络
    Flutter视图原理之StatefulWidget,InheritedWidget
    js中高级部分知识点总结第二篇
    Shell脚本——提取目录名和文件名
    terminal下环境不统一导致的程序报错(powersell改cmd)
    计算机毕业设计Java居民个人健康信息与个人健康服务综合平台(源码+mysql数据库+系统+lw文档)
    计算机网络高频面试题
    大规模分布式链路分析计算在字节跳动的实践
    java中内存泄漏和内存溢出指什么呢?
  • 原文地址:https://blog.csdn.net/qq_43751200/article/details/126078259