Cookie详解

首先我们先创建一个Maven,然后补齐main里面的包,之后我们将web.xml里面的进行复制过来,之后将大项目里面的pom.xml里面复制过来。如下所示: 

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>untitled2</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>Cookie</artifactId>
    <packaging>war</packaging>
    <dependencies>
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.3</version>
    </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

我们将里面没有用的东西删除掉即可,相关详细步骤我们再之前的博客里面已经提过了。

我们进行刷新之后,发现全部导入进去了。

 这就是我们准备工作完成了。

1.1会话

会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话

有状态会话一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过。称之为有状态会话。

你能怎么能证明自己是哪所大学的学生:

在你和你的大学之间作为两个对象:我们可以通过以下两种方法

1.交学费的发票凭证     你的大学给你发票

2.学校登记     你的大学标记你来过了

同样的,我们借此来思考一个网站怎么证明你来过:

客户端     服务端(怎么让服务端证明客户端已经来过呢):以下方法:

1.服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了;(服务端给客户端发了一个Cookie)客户端访问的时候带的Cookie.

2.服务器登记你来过了,下次你来的时候我来匹配你;session(session就是在服务器端)

无状态会话:打开浏览器并关闭

1.2保存会话的两种技术

cookie:客户端技术(响应:服务器将Cookie发给客户端,请求:客户端将Cookie带到服务器)客户端携带的

session:服务器技术,利用这个技术可以保存用户的会话信息,我们可以把信息或者数据放在Session中!

我们之前学到的能把信息或者东西放到一个东西里面让别人去取是ServletContext。用了setAttribute。ServletContext详解_蕾峰的博客-CSDN博客 

常见场景:网站登录之后,下次可以不用再登录了第二次访问直接就登录进去了。

比如我们再登录CSDN的时候,首次登录需要密码,当我们让网站记住密码,下次再次重新点开CSDN的界面的时候,我们发现直接登录上去了。

我们先要学习一个东西,要首先看他的源码。

我们创建一个新的类之后,写入Cookie,如下所示:

我们按住ctrl键,进入源码界面:

 这个类可以被克隆(实现了可以克隆的接口):

public class Cookie implements Cloneable, Serializable {

我们点击进行下载它的源码:

 我们来进行查看源码如下所示:
设置一些文件:

 private static final String LSTRING_FILE =

设置一些键值对一样的东西:

private String name;	// NAME= ... "$Name" style is reserved
    private String value;	// value of NAME

设置一些守护:(设置他的有效域)

private String domain;	// ;Domain=VALUE ... domain that sees cookie

设置保存的时间(即为过期时间)

private int maxAge = -1;	// ;Max-Age=VALUE ... cookies auto-expire

设置注册一些版本:

private int version = 0;	// ;Version=1 ... means RFC 2109++ style

得到一些方法:

private String path;	// ;Path=VALUE ... URLs that see the cookie

我们打开Structure可以发现在这些属性有对应的get和set方法。有了get和set方法可以对属性进行一些操作。说白了就是在操作Cookie这个类。

我们要实现保存用户上一次访问的时间,我们的思维逻辑如下所示:

首先我们先解决中文乱码问题:

 req.setCharacterEncoding("utf-8");
        //响应
        resp.setCharacterEncoding("utf-8");

之后我们来设置获取输入与输出的信息:

 //想要客户端返回一些字符串,需要返回一个输出对象。(响应)用Response.
        PrintWriter out = resp.getWriter();
        // 请求是客户端拿着cookie到服务器。服务器获取Cookie。
        //Cookie,服务器给了客户端,客户端带来的时候是服务器端需要从客户端获取,是Request。
        Cookie[] cookies = req.getCookies();  //这里返回数组,说明cookie可能存在多个(多个标志)。

之后我们利用if--else语句进行判断是否有Cookie:

/判断cookie是否存在
        if  (cookies!=null){   //不等于null,说明cookie有值
//如果存在cookie怎么办:
            out.write("你上一次访问的时间是:");

           
            //第一次访问一定是没有值的
        }else{
            out.write("这是您第一次访问本站");
        }

当我们判断没有值的时候,我们需要传递一个Cookie,我们设置Cookie如下所示:

/客户端第一次访问服务器的时候,服务器需要给客户端发一个Cookie。
        //服务器给客户端响应一个cookie:
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
        resp.addCookie(cookie);  //添加一个Cookie,他的参数是cookie这样子一个对象
    }

 我们查看Cookie里面发现如下所示:

 Cookie只能存String,存在局限性,说明存的东西比较少

接下来我们进行设计如果Cookie存在的话代码如何设计:

 if  (cookies!=null){   //不等于null,说明cookie有值
        //如果存在cookie怎么办
            //如果存在我们要取出我们想取出的数据
            out.write("你上一次访问的时间是:");
           //进行遍历数据
            //两种for循环:
            //for(Cookie  cookie:cookies){}
            //我们更倾向于使用下一种for循环(更加的灵活)
            for (int i=0;i<cookies.length;i++){
                Cookie cookie=cookies[i];
                //通过for循环进行遍历之后,我们拿到了每个cookie。
                //获取Cookie的名字
                //获取了cookie的名字之后,我们需要与服务器响应的Cookie进行对比。
                if(cookie.getName().equals("lastLoginTime")){
                    //获取cookie中的值
                    cookie.getValue();
                    //我们获取了cookie的值之后,我们想要将他输出出去,以Date的形式进行输出。
                    //我们获取的cookie现在是一个字符串,我们需要将他进行解析,将他解析为长整型之类的在把他转化为字符串。
                    //把字符串变成时间戳了。
                    long lastLoginTime = Long.parseLong(cookie.getValue());
                    //把时间戳变成一个对象(new的Date为util包下的)
                    Date date = new Date(lastLoginTime);
                    //之后我们需要将date转换为String,有的方法过期了但是也可以用,我们采用格林威治时间(toLocaleString)
                    out.write(date.toLocaleString());

                }
            }
            //第一次访问一定是没有值的
        }else{
            out.write("这是您第一次访问本站");
        }

我们完成代码的设计之后,我们进行在web.xml里面进行注册:

<servlet>
        <servlet-name>CookieDemo01</servlet-name>
        <servlet-class>com.rgf.servlet.CookieDemo01</servlet-class> 
    </servlet>
    <servlet-mapping>
        <servlet-name>CookieDemo01</servlet-name>
        <url-pattern>/c1</url-pattern>
    </servlet-mapping>

之后我们进行配置Tomcat:

 配置完毕之后,点击OK。我们点击运行之后,发现出现如下所示:

出现了乱码问题,我们在进行UTF-8地方加入这行代码:
 

resp.setContentType("text/html");

 我们重新运行之后如下所示:

我们发现成功运行出来了。

我们进入浏览器,点击开发者工具,点击Application,我们发现Cookies,进入之后,我们发现lastLoginTime,除了这个以外,我们还发现其他的cookie,

 我们将cookie进行删除后,

 重新进入页面如下所示:

 我们再次刷新之后,我们发现如下所示:

服务器再次给客户端发送了一个新的cookie。

我们发现除了我们设置的Cookie之外,我们还有一个Cookie:

 JSESSIONID,这是服务器端,只要一连上浏览器就会开启一次会话。我们将浏览器关了之后就没有啦。我们每次刷新都会出现一个不同的时间,都会发送一个新的Cookie。

我们为什么会获取这个时间,我们通过分析网站请求来看:

我们重新进入刷新,点开Network,点开Headers,我们发现 Response(响应)里面的:

Set-Cookie:lastLoginTime=1662384316731

Cookie是一个键值对的形式

我们来看Request里面:

 我们发现这里面也有一个Cookie:

Cookie:JSESSIONID=837B90BDAA8682E02EB26870323F909A; lastLoginTime=1662366474311

我们发现这个Cookie里面有两组键值对。

其中Request里面的lastLoginTime=1662366474311是我们上一次登录的时间,而Response里面的lastLoginTime=1662384316731为响应回来的新的登录时间。

我们将浏览器关掉Cookie还会存在么:

我们进行访问发现出现如下所示:

 发现Cookie不见了,这个会话就是浏览器关了,这个会话就结束了。

我们将浏览器里面的Cookie进行清除之后,才发现第一次进入了我们所编写的这是您第一次访问本站。而我们在第一次访问的时候出现的是你上一次访问的时间是:,原因是浏览器会默认在Cookie中存放一些数据,所以不可能判断Cookie为空,所以我们直接按存有东西进行响应。即会出现你上一次访问的时间是。

如何将Cookie进行多层会话呢?我们进入Cookie的源码界面进行查看:

我们发现Cookie里面的源码如下所示:

其中的代码:

可以设置存活的时间:setMaxAge(int expiry)。

expiry为有效期的意思

我们在设置Cookie里面的代码进行设计如下所示:

//服务器给客户端响应一个cookie:
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
        //设置Cookie有效期为一天。 
        cookie.setMaxAge(24*60*60);
        
        resp.addCookie(cookie);  //添加一个Cookie,他的参数是cookie这样子一个对象

然后点击运行如下所示:

 我们进行刷新发现出现如下所示:

 我们发现此时Cookie为lastLogintime的值为:1662448381522

之后我们关闭浏览器,然后再重新打开浏览器。

我们发现浏览器关掉之后仍然能再次拿到Cookie,

我们点击Network进行查看:
 我们发现Set-Cookie里面出现的时间cookie到2022年9月7日才结束。里面多了一个Max-Age(多了一个最大的时间)刚开始的时候,我们只有一个lastLoginTime。

我们在Request里面进行查看Cookie,发现他的值为:lastLoginTime=1662448267811

 我们所编写的代码为获取上一次访问的时间,所以lastLoginTime一直在发生变化。

浏览器关闭之后Cookie仍然存在,这种行为是非常不安全的。

我们对实现上一次的访问时间的完整代码如下所示:

package com.rgf.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.crypto.Data;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

//保存用户上一次访问的时间(我们也可以使用IO进行实现,
// 就是他过来的时候你把东西保存在本地,写一个文件,下次过来的时候再去读他,把那个所写的文件带上,把里面的东西读出来,这种方法比较低级一点)
public class CookieDemo01 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //服务器告诉你你来的时间,把这个时间封装成为一个信件,然后给了你,你下次来的时候带来,服务器就知道你来了。
        //首先解决中文乱码问题:
        //请求
        req.setCharacterEncoding("utf-8");
        //响应
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");
        //想要客户端返回一些字符串,需要返回一个输出对象。(响应)用Response.
        PrintWriter out = resp.getWriter();
        // 请求是客户端拿着cookie到服务器。服务器获取Cookie。
        //Cookie,服务器给了客户端,客户端带来的时候是服务器端需要从客户端获取,是Request。
        Cookie[] cookies = req.getCookies();  //这里返回数组,说明cookie可能存在多个(多个标志)。

        //我们为了要获取Cookie,首先要判断Cookie是否存在,这是一个正常的程序逻辑。

        //判断cookie是否存在
        if  (cookies!=null){   //不等于null,说明cookie有值
        //如果存在cookie怎么办
            //如果存在我们要取出我们想取出的数据
            out.write("你上一次访问的时间是:");
           //进行遍历数据
            //两种for循环:
            //for(Cookie  cookie:cookies){}
            //我们更倾向于使用下一种for循环(更加的灵活)
            for (int i=0;i<cookies.length;i++){
                Cookie cookie=cookies[i];
                //通过for循环进行遍历之后,我们拿到了每个cookie。
                //获取Cookie的名字
                //获取了cookie的名字之后,我们需要与服务器响应的Cookie进行对比。
                if(cookie.getName().equals("lastLoginTime")){
                    //获取cookie中的值
                    cookie.getValue();
                    //我们获取了cookie的值之后,我们想要将他输出出去,以Date的形式进行输出。
                    //我们获取的cookie现在是一个字符串,我们需要将他进行解析,将他解析为长整型之类的在把他转化为字符串。
                    //把字符串变成时间戳了。
                    long lastLoginTime = Long.parseLong(cookie.getValue());
                    //把时间戳变成一个对象(new的Date为util包下的)
                    Date date = new Date(lastLoginTime);
                    //之后我们需要将date转换为String,有的方法过期了但是也可以用,我们采用格林威治时间(toLocaleString)
                    out.write(date.toLocaleString());

                }
            }
            //第一次访问一定是没有值的
        }else{
            out.write("这是您第一次访问本站");
        }

  //客户端第一次访问服务器的时候,服务器需要给客户端发一个Cookie。
        //服务器给客户端响应一个cookie:
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
        //设置Cookie有效期为一天。
        cookie.setMaxAge(24*60*60);

        resp.addCookie(cookie);  //添加一个Cookie,他的参数是cookie这样子一个对象
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

我们对Cookie的总结如下所示:

1.从请求中拿到Cookie信息

2.服务器响应给客户端Cookie。

我们所使用的方法有:

Cookie[] cookies = req.getCookies();  //获得Cookie
cookie.getName()    //获得cookie中的key
cookie.getValue();  //获得cookie中的value
new Cookie("lastLoginTime", System.currentTimeMillis()+"");  //新建一个cookie
cookie.setMaxAge(24*60*60)  //设置cookie的有效期
resp.addCookie(cookie)  //响应给客户端一个cookie

 我们自身电脑也有好多cookie,我们可以打开C盘进行查看:


cookie:一般会保存在本地的用户目录下 Appdata文件夹里面

这是本机保存的部分Cookies。 

cookie为什么会保存,就是因为cookie在本地中会有个缓存文件。

我们进行思考:一个网站cookie是否存在上限?我们进行查看细节问题:
              (1)一个Cookie只能保存一个信息;

               (2)一个web站点可以给浏览器发送多个cookie。浏览器上限大概为300个cookie,每个站点最多存放20个cookie。

              (3)cookie有大小限制,限制为4KB.1KB=1024B,4KB=4096B。

删除cookie:

(1)不设置有效期,关闭浏览器,自动失效;

(2)设置有效期时间为0;

我们进行设置做到删除cookie的代码:

package com.rgf.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.crypto.Data;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;


public class CookieDemo02 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //创建一个Cookie,名字必须要和删除的名字一致
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
        //将cookie有效期设置为0,立马过期
        cookie.setMaxAge(0);
        resp.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

之后我们进行编写web.xml。如下所示:

 <servlet>
        <servlet-name>CookieDemo02</servlet-name>
        <servlet-class>com.rgf.servlet.CookieDemo02</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CookieDemo02</servlet-name>
        <url-pattern>/c2</url-pattern>
    </servlet-mapping>

我们进行运行之后如下所示:

 我们打开Application进行查看如下:

我们发现Cookie没有了。这是因为此时的Cookie已经过时了。 

我们再进行请求c1的时候,如下所示:

此时又有了cookie。

然后再请求c2的时候,cookie如下所示:

此时cookie已经又过期了。这就达到了删除cookie的目的。

 我们该如何做到中文数据的传递:

我们设计的代码如下所示:

package com.rgf.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import static java.lang.System.out;

//中文数据怎么传递
public class CookieDemo03 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //首先解决中文乱码问题:
        //请求
        req.setCharacterEncoding("utf-8");
        //响应
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");


        Cookie[] cookies = req.getCookies();  //这里返回数组,说明cookie可能存在多个(多个标志)。

        PrintWriter out = resp.getWriter();
        //我们为了要获取Cookie,首先要判断Cookie是否存在,这是一个正常的程序逻辑。

        //判断cookie是否存在
        if  (cookies!=null){   //不等于null,说明cookie有值
            //如果存在cookie怎么办
            //如果存在我们要取出我们想取出的数据
            out.write("你上一次访问的时间是:");
            //进行遍历数据
            //两种for循环:
            //for(Cookie  cookie:cookies){}
            //我们更倾向于使用下一种for循环(更加的灵活)
            for (int i=0;i<cookies.length;i++){
                Cookie cookie=cookies[i];
                //通过for循环进行遍历之后,我们拿到了每个cookie。
                //获取Cookie的名字
                //获取了cookie的名字之后,我们需要与服务器响应的Cookie进行对比。
                if(cookie.getName().equals("name")){
                    out.println(cookie.getValue());

                }
            }
            //第一次访问一定是没有值的
        }else{
            out.write("这是您第一次访问本站");
        }

        
        Cookie cookie = new Cookie("name","蕾峰编程");
        resp.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

之后我们编辑web.xml的文件:

<servlet>
        <servlet-name>CookieDemo03</servlet-name>
        <servlet-class>com.rgf.servlet.CookieDemo03</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CookieDemo03</servlet-name>
        <url-pattern>/c3</url-pattern>
    </servlet-mapping>

我们运行之后如下所示:

 

 Tomcat8之后cookie就可以存放中文啦

如果我们再编程中遇到无法去传送中文,我们可以利用:
编码解码进行解决:
编码:URLEncoder.encode("蕾峰编程","utf-8")

有编码,我们后台进行获取的时候就需要有解码:
URLDecoder.decode(cookie.getValue(),"UTF-8")。

代码如下所示:
 

package com.rgf.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;

import static java.lang.System.out;

//中文数据怎么传递
public class CookieDemo03 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //首先解决中文乱码问题:
        //请求
        req.setCharacterEncoding("utf-8");
        //响应
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");

        Cookie[] cookies = req.getCookies();  //这里返回数组,说明cookie可能存在多个(多个标志)。

        PrintWriter out = resp.getWriter();
        //我们为了要获取Cookie,首先要判断Cookie是否存在,这是一个正常的程序逻辑。

        //判断cookie是否存在
        if  (cookies!=null){   //不等于null,说明cookie有值
            //如果存在cookie怎么办
            //如果存在我们要取出我们想取出的数据
            out.write("你上一次访问的时间是:");
            //进行遍历数据
            //两种for循环:
            //for(Cookie  cookie:cookies){}
            //我们更倾向于使用下一种for循环(更加的灵活)
            for (int i=0;i<cookies.length;i++){
                Cookie cookie=cookies[i];
                //通过for循环进行遍历之后,我们拿到了每个cookie。
                //获取Cookie的名字
                //获取了cookie的名字之后,我们需要与服务器响应的Cookie进行对比。
                if(cookie.getName().equals("name")){
                    URLDecoder.decode(cookie.getValue(),"UTF-8");
                    //解码
                    out.println(URLDecoder.decode(cookie.getValue(),"UTF-8"));
                }
            }
            //第一次访问一定是没有值的
        }else{
            out.write("这是您第一次访问本站");
        }

        //编码,有编码就要有解码
        Cookie cookie = new Cookie("name", URLEncoder.encode("蕾峰编程","utf-8"));
        resp.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

我们运行之后如下所示:

发现成功进行了输出。 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一直再追梦

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

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

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

打赏作者

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

抵扣说明:

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

余额充值