• JavaEE | 一文吃透Cookie


    在这里插入图片描述

    👑 博主简介
       🥇 Java领域新星创作者
       🥇 阿里云开发者社区专家博主、星级博主、技术博主
    🤝 交流社区BoBooY(优质编程学习笔记社区)

    前言:本章我们将学习会话跟踪技术中的Cookie与Session,它在我们整个JavaEE的知识体系中是非常重要的,本节我们先介绍Cookie,废话不多说,直接上正文!

    1、会话跟踪技术

    1.1、概述

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

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


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

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

    问:为什么一个会话中的多次请求要共享数据?有了这个数据共享功能后能实现哪些功能?

    答:

    • 购物车,在选完商品加入购物车后,当点击去结算时显示之前加入购物车的商品信息时就需要用到共享数据;
    • 登录,登录后展示个人信息;
    • 登录页面 ” 记住我 “,在第一次登陆成功后,下次登录会自动填充账号和密码
    • 登录页面的验证码功能,生成验证码和输入验证码点击注册这也是两次请求,这两次请求的数据之间要进行对比

    问:为什么现在浏览器和服务器不支持数据共享呢

    答:

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

    1.2、实现方式

    会话跟踪技术的实现方式有:Cookie(客户端会话跟踪技术)、Session(服务端会话跟踪技术)

    两者之间的区别:Cookie是存储在浏览器端而Session是存储在服务器端

    2、Cookie

    2.1、Cookie的基本使用

    2.1.1、概念

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

    2.1.2、Cookie的工作流程

    在这里插入图片描述

    • 服务端提供了两个Servlet,分别是ServletA和ServletB
    • 浏览器发送HTTP请求1给服务端,服务端ServletA接收请求并进行业务处理
    • 服务端ServletA在处理的过程中可以创建一个Cookie对象并将name=zs的数据存入Cookie
    • 服务端ServletA在响应数据的时候,会把Cookie对象响应给浏览器
    • 浏览器接收到响应数据,会把Cookie对象中的数据存储在浏览器内存中,此时浏览器和服务端就建立了一次会话
    • 在同一次会话中浏览器再次发送HTTP请求2给服务端ServletB,浏览器会携带Cookie对象中的所有数据
    • ServletB接收到请求和数据后,就可以获取到存储在Cookie对象中的数据,这样同一个会话中的多次请求之间就实现了数据共享

    2.1.3、Cookie的基本使用

    对于Cookie的使用,我们更关注的应该是后台代码如何操作Cookie,对于Cookie的操作主要分两大类,本别是发送Cookie获取Cookie,对于上面这两块内容,分别该如何实现呢?

    1)发送Cookie

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

    《Cookie发送案例》
    • 创建Maven项目cookie-demo,并在pom.xml添加依赖
    
    <dependency>
        <groupId>javax.servletgroupId>
        <artifactId>javax.servlet-apiartifactId>
        <version>3.1.0version>
        <scope>providedscope>
    dependency>
    
    <dependency>
        <groupId>javax.servlet.jspgroupId>
        <artifactId>jsp-apiartifactId>
        <version>2.2version>
        <scope>providedscope>
    dependency>
    
    <dependency>
        <groupId>jstlgroupId>
        <artifactId>jstlartifactId>
        <version>1.2version>
    dependency>
    <dependency>
        <groupId>taglibsgroupId>
        <artifactId>standardartifactId>
        <version>1.1.2version>
    dependency>
    
    • 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
    • 编写Servlet类,名称为AServlet,并在Servlet中创建Cookie对象,存入数据,发送给前端
    package com.bby; /**
     * @author BoBooY
     * @date 2022/11/5 15:21
     */
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    
    @WebServlet("/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", "bby");
            //2.发送Cookie,response
            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
    • 配置Tomcat

    在这里插入图片描述

    • 启动项目测试,浏览器查看Cookie的值

    访问http://localhost:8080/aServlet

    方式一:浏览器设置中查看,此处使用 Edge浏览器查看(新版火狐和谷歌浏览器都不能查看具体信息)

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    方式二:浏览器(此处以谷歌浏览器为例)中按下 F12
    在这里插入图片描述


    2)获取Cookie

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

    《Cookie获取案例》
    • 编写一个新Servlet类,名称为BServlet
    package com.bby;
    
    import javax.servlet.ServletException;
    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;
    
    /**
     * @author BoBooY
     * @date 2022/11/5 16:02
     */
    @WebServlet("/bServlet")
    public class BServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取Cookie
            //1. 获取Cookie数组
            Cookie[] cookies = req.getCookies();
            //2. 遍历数组
            for (Cookie cookie : cookies) {
                //3. 获取数据
                String name = cookie.getName();
                if (name.equals("username")) {
                    String value = cookie.getValue();
                    System.out.println(name + ":" + value);
                }
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doGet(req, resp);
        }
    }
    
    • 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
    • 37
    • 启动项目测试

    在这里插入图片描述

    2.2、Cookie的原理分析

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

    • 响应头:set-cookie
    • 请求头:cookie

    在这里插入图片描述

    • 前面的案例中已经能够实现,AServlet给前端发送Cookie,BServlet从request中获取Cookie的功能
    • 对于AServlet响应数据的时候,Tomcat服务器都是基于HTTP协议来响应数据
    • 当Tomcat发现后端要返回的是一个Cookie对象之后,Tomcat就会在响应头中添加一行数据Set-Cookie:username=zs
    • 浏览器获取到响应结果后,从响应头中就可以获取到Set-Cookie对应值username=zs,并将数据存储在浏览器的内存中
    • 浏览器再次发送请求给BServlet的时候,浏览器会自动在请求头中添加Cookie: username=zs发送给服务端BServlet
    • Request对象会把请求头中cookie对应的值封装成一个个Cookie对象,最终形成一个数组
    • BServlet通过Request对象获取到Cookie[]后,就可以从中获取自己需要的数据
    《验证上述结论》
    • 访问http://localhost:8080/bServlet

    从响应头获取到Set-Cookie对应值username=bby

    在这里插入图片描述

    • 访问http://localhost:8080/bServlet

    向请求头中添加Cookie: username=bby

    在这里插入图片描述

    2.3、Cookie的使用细节

    在使用Cookie时我们要注意两点:第一个是Cookie的存活时间,第二个是Cookie如何存储中文

    2.3.1、Cookie的存活时间

    思考:当我们关闭浏览器后再重新打开,AServlet响应存有的username=bby的Cookie对象给浏览器还存在吗?

    结论:不存在,当我们关闭浏览器后再通过BServlet访问这个Cookie对象时就获取不到了

    原因:默认情况下,Cookie存储在浏览器内存中,当浏览器关闭,内存释放,则Cookie被销毁

    《实际案例分析》
    • 分析

    当我们登录的时候在账号和密码下方有一个“记住我”的按钮,这个功能就相当于第一次输入用户名和密码并勾选后进行登录,下次再登陆的时候,用户名和密码就会被自动填充,不需要再重新输入登录。但是我们要是使用默认的Cookie,浏览器一关,Cookie就会从浏览器内存中被删除,这个功能就无法实现了

    在这里插入图片描述

    • 如何将Cookie持久化存储?

    Cookie其实已经为我们提供好了对应的API来完成这件事,这个API就是setMaxAge


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

    参数值为:

    1.正数:将Cookie写入浏览器所在电脑的硬盘,持久化存储。到时间自动删除

    2.负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则Cookie被销毁

    3.零:删除对应Cookie


    《案例:设置Cookie存活时间》
    • 编写Servlet
    package com.bby;
    /**
     * @author BoBooY
     * @date 2022/11/5 15:21
     */
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    
    @WebServlet("/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", "bby");
            cookie.setMaxAge(7*24*60*60); //7天,这样写便于阅读
            //cookie.setMaxAge(604800); //不易阅读(可以使用注解弥补),程序少进行一次计算
            //2.发送Cookie,response
            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
    • 运行项目测试

    先访问一次http://localhost:8080/aServlet,然后关闭浏览器并重启,访问http://localhost:8080/bServlet,能在控制台打印出username:bby,说明Cookie没有随着浏览器关闭而被销毁

    在这里插入图片描述

    在这里插入图片描述

    可以看到Cookie的创建时间与到期时间相差一周,如下图

    在这里插入图片描述

    2.3.2、Cookie存储中文

    Cookie直接存储中文会发生什么?

    • 修改代码

    在这里插入图片描述

    • 运行测试

    在这里插入图片描述

    结论:Cookie不能直接存储中文

    解决方式:先对中文进行URL编码,采用URLEncoder.encode(),将编码后的值存入Cookie中,再将获取到的值进行解码

    • 编码
    String value = "啵啵鱼";
    //对中文进行URL编码
    value = URLEncoder.encode(value, "UTF-8");
    //将编码后的值存入Cookie中
    Cookie cookie = new Cookie("username",value);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 解码
    //将获取的Cookie值进行解码
    //URL解码
    value = URLDecoder.decode(value,"UTF-8");
    
    • 1
    • 2
    • 3

    这样,我们就可以将中文存入Cookie中进行使用。


    下节我们讲解Session,To be continued…

    尾言:创作不易,如果本文的内容对您有帮助,还望客官可以三连支持一下博主,👍(点赞)+✏️(评论)+⭐️(收藏)是我创作的巨大动力!

  • 相关阅读:
    java某百货店POS积分管理系统积分点更新生成以及通票回收处理源代码+LW
    队列的链式存储结构
    Vue前端页面打印
    ETCD快速入门-03 常用命令
    大学生网页设计模板 静态HTML个人主页网页作业成品 DIV CSS个人介绍主题静态网页
    Decomposed Meta-Learning for Few-Shot Named Entity Recognition
    面试25题
    Linux入门教程:P13->磁盘管理类
    STL 中的string 容器方法与API
    JVM阶段(5)-引用系列
  • 原文地址:https://blog.csdn.net/qq_58233406/article/details/127722858