• Cookie详解


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

    1. "1.0" encoding="UTF-8"?>
    2. "http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. untitled2
    5. org.example
    6. 1.0-SNAPSHOT
    7. 4.0.0
    8. Cookie
    9. war
    10. javax.servlet.jsp
    11. javax.servlet.jsp-api
    12. 2.3.3
    13. javax.servlet
    14. javax.servlet-api
    15. 4.0.1
    16. provided

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

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

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

    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 =

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

    1. private String name; // NAME= ... "$Name" style is reserved
    2. 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这个类。

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

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

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

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

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

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

    1. /判断cookie是否存在
    2. if (cookies!=null){ //不等于null,说明cookie有值
    3. //如果存在cookie怎么办:
    4. out.write("你上一次访问的时间是:");
    5. //第一次访问一定是没有值的
    6. }else{
    7. out.write("这是您第一次访问本站");
    8. }

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

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

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

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

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

    1. if (cookies!=null){ //不等于null,说明cookie有值
    2. //如果存在cookie怎么办
    3. //如果存在我们要取出我们想取出的数据
    4. out.write("你上一次访问的时间是:");
    5. //进行遍历数据
    6. //两种for循环:
    7. //for(Cookie cookie:cookies){}
    8. //我们更倾向于使用下一种for循环(更加的灵活)
    9. for (int i=0;i
    10. Cookie cookie=cookies[i];
    11. //通过for循环进行遍历之后,我们拿到了每个cookie。
    12. //获取Cookie的名字
    13. //获取了cookie的名字之后,我们需要与服务器响应的Cookie进行对比。
    14. if(cookie.getName().equals("lastLoginTime")){
    15. //获取cookie中的值
    16. cookie.getValue();
    17. //我们获取了cookie的值之后,我们想要将他输出出去,以Date的形式进行输出。
    18. //我们获取的cookie现在是一个字符串,我们需要将他进行解析,将他解析为长整型之类的在把他转化为字符串。
    19. //把字符串变成时间戳了。
    20. long lastLoginTime = Long.parseLong(cookie.getValue());
    21. //把时间戳变成一个对象(new的Date为util包下的)
    22. Date date = new Date(lastLoginTime);
    23. //之后我们需要将date转换为String,有的方法过期了但是也可以用,我们采用格林威治时间(toLocaleString)
    24. out.write(date.toLocaleString());
    25. }
    26. }
    27. //第一次访问一定是没有值的
    28. }else{
    29. out.write("这是您第一次访问本站");
    30. }

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

    1. CookieDemo01
    2. com.rgf.servlet.CookieDemo01
    3. CookieDemo01
    4. /c1

    之后我们进行配置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里面的代码进行设计如下所示:

    1. //服务器给客户端响应一个cookie:
    2. Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
    3. //设置Cookie有效期为一天。
    4. cookie.setMaxAge(24*60*60);
    5. 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仍然存在,这种行为是非常不安全的。

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

    1. package com.rgf.servlet;
    2. import javax.servlet.ServletException;
    3. import javax.servlet.http.Cookie;
    4. import javax.servlet.http.HttpServlet;
    5. import javax.servlet.http.HttpServletRequest;
    6. import javax.servlet.http.HttpServletResponse;
    7. import javax.xml.crypto.Data;
    8. import java.io.IOException;
    9. import java.io.PrintWriter;
    10. import java.util.Date;
    11. //保存用户上一次访问的时间(我们也可以使用IO进行实现,
    12. // 就是他过来的时候你把东西保存在本地,写一个文件,下次过来的时候再去读他,把那个所写的文件带上,把里面的东西读出来,这种方法比较低级一点)
    13. public class CookieDemo01 extends HttpServlet {
    14. @Override
    15. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    16. //服务器告诉你你来的时间,把这个时间封装成为一个信件,然后给了你,你下次来的时候带来,服务器就知道你来了。
    17. //首先解决中文乱码问题:
    18. //请求
    19. req.setCharacterEncoding("utf-8");
    20. //响应
    21. resp.setCharacterEncoding("utf-8");
    22. resp.setContentType("text/html");
    23. //想要客户端返回一些字符串,需要返回一个输出对象。(响应)用Response.
    24. PrintWriter out = resp.getWriter();
    25. // 请求是客户端拿着cookie到服务器。服务器获取Cookie。
    26. //Cookie,服务器给了客户端,客户端带来的时候是服务器端需要从客户端获取,是Request。
    27. Cookie[] cookies = req.getCookies(); //这里返回数组,说明cookie可能存在多个(多个标志)。
    28. //我们为了要获取Cookie,首先要判断Cookie是否存在,这是一个正常的程序逻辑。
    29. //判断cookie是否存在
    30. if (cookies!=null){ //不等于null,说明cookie有值
    31. //如果存在cookie怎么办
    32. //如果存在我们要取出我们想取出的数据
    33. out.write("你上一次访问的时间是:");
    34. //进行遍历数据
    35. //两种for循环:
    36. //for(Cookie cookie:cookies){}
    37. //我们更倾向于使用下一种for循环(更加的灵活)
    38. for (int i=0;i
    39. Cookie cookie=cookies[i];
    40. //通过for循环进行遍历之后,我们拿到了每个cookie。
    41. //获取Cookie的名字
    42. //获取了cookie的名字之后,我们需要与服务器响应的Cookie进行对比。
    43. if(cookie.getName().equals("lastLoginTime")){
    44. //获取cookie中的值
    45. cookie.getValue();
    46. //我们获取了cookie的值之后,我们想要将他输出出去,以Date的形式进行输出。
    47. //我们获取的cookie现在是一个字符串,我们需要将他进行解析,将他解析为长整型之类的在把他转化为字符串。
    48. //把字符串变成时间戳了。
    49. long lastLoginTime = Long.parseLong(cookie.getValue());
    50. //把时间戳变成一个对象(new的Date为util包下的)
    51. Date date = new Date(lastLoginTime);
    52. //之后我们需要将date转换为String,有的方法过期了但是也可以用,我们采用格林威治时间(toLocaleString)
    53. out.write(date.toLocaleString());
    54. }
    55. }
    56. //第一次访问一定是没有值的
    57. }else{
    58. out.write("这是您第一次访问本站");
    59. }
    60. //客户端第一次访问服务器的时候,服务器需要给客户端发一个Cookie。
    61. //服务器给客户端响应一个cookie:
    62. Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
    63. //设置Cookie有效期为一天。
    64. cookie.setMaxAge(24*60*60);
    65. resp.addCookie(cookie); //添加一个Cookie,他的参数是cookie这样子一个对象
    66. }
    67. @Override
    68. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    69. doGet(req, resp);
    70. }
    71. }

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

    1.从请求中拿到Cookie信息

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

    我们所使用的方法有:

    1. Cookie[] cookies = req.getCookies(); //获得Cookie
    2. cookie.getName() //获得cookie中的key
    3. cookie.getValue(); //获得cookie中的value
    4. new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie
    5. cookie.setMaxAge(24*60*60) //设置cookie的有效期
    6. 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的代码:

    1. package com.rgf.servlet;
    2. import javax.servlet.ServletException;
    3. import javax.servlet.http.Cookie;
    4. import javax.servlet.http.HttpServlet;
    5. import javax.servlet.http.HttpServletRequest;
    6. import javax.servlet.http.HttpServletResponse;
    7. import javax.xml.crypto.Data;
    8. import java.io.IOException;
    9. import java.io.PrintWriter;
    10. import java.util.Date;
    11. public class CookieDemo02 extends HttpServlet {
    12. @Override
    13. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    14. //创建一个Cookie,名字必须要和删除的名字一致
    15. Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
    16. //将cookie有效期设置为0,立马过期
    17. cookie.setMaxAge(0);
    18. resp.addCookie(cookie);
    19. }
    20. @Override
    21. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    22. doGet(req, resp);
    23. }
    24. }

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

    1. CookieDemo02
    2. com.rgf.servlet.CookieDemo02
    3. CookieDemo02
    4. /c2

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

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

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

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

    此时又有了cookie。

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

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

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

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

    1. package com.rgf.servlet;
    2. import javax.servlet.ServletException;
    3. import javax.servlet.http.Cookie;
    4. import javax.servlet.http.HttpServlet;
    5. import javax.servlet.http.HttpServletRequest;
    6. import javax.servlet.http.HttpServletResponse;
    7. import java.io.IOException;
    8. import java.io.PrintWriter;
    9. import java.util.Date;
    10. import static java.lang.System.out;
    11. //中文数据怎么传递
    12. public class CookieDemo03 extends HttpServlet {
    13. @Override
    14. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    15. //首先解决中文乱码问题:
    16. //请求
    17. req.setCharacterEncoding("utf-8");
    18. //响应
    19. resp.setCharacterEncoding("utf-8");
    20. resp.setContentType("text/html");
    21. Cookie[] cookies = req.getCookies(); //这里返回数组,说明cookie可能存在多个(多个标志)。
    22. PrintWriter out = resp.getWriter();
    23. //我们为了要获取Cookie,首先要判断Cookie是否存在,这是一个正常的程序逻辑。
    24. //判断cookie是否存在
    25. if (cookies!=null){ //不等于null,说明cookie有值
    26. //如果存在cookie怎么办
    27. //如果存在我们要取出我们想取出的数据
    28. out.write("你上一次访问的时间是:");
    29. //进行遍历数据
    30. //两种for循环:
    31. //for(Cookie cookie:cookies){}
    32. //我们更倾向于使用下一种for循环(更加的灵活)
    33. for (int i=0;i
    34. Cookie cookie=cookies[i];
    35. //通过for循环进行遍历之后,我们拿到了每个cookie。
    36. //获取Cookie的名字
    37. //获取了cookie的名字之后,我们需要与服务器响应的Cookie进行对比。
    38. if(cookie.getName().equals("name")){
    39. out.println(cookie.getValue());
    40. }
    41. }
    42. //第一次访问一定是没有值的
    43. }else{
    44. out.write("这是您第一次访问本站");
    45. }
    46. Cookie cookie = new Cookie("name","蕾峰编程");
    47. resp.addCookie(cookie);
    48. }
    49. @Override
    50. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    51. doGet(req, resp);
    52. }
    53. }

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

    1. CookieDemo03
    2. com.rgf.servlet.CookieDemo03
    3. CookieDemo03
    4. /c3

    我们运行之后如下所示:

     

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

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

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

    代码如下所示:
     

    1. package com.rgf.servlet;
    2. import javax.servlet.ServletException;
    3. import javax.servlet.http.Cookie;
    4. import javax.servlet.http.HttpServlet;
    5. import javax.servlet.http.HttpServletRequest;
    6. import javax.servlet.http.HttpServletResponse;
    7. import java.io.IOException;
    8. import java.io.PrintWriter;
    9. import java.net.URLDecoder;
    10. import java.net.URLEncoder;
    11. import java.util.Date;
    12. import static java.lang.System.out;
    13. //中文数据怎么传递
    14. public class CookieDemo03 extends HttpServlet {
    15. @Override
    16. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    17. //首先解决中文乱码问题:
    18. //请求
    19. req.setCharacterEncoding("utf-8");
    20. //响应
    21. resp.setCharacterEncoding("utf-8");
    22. resp.setContentType("text/html");
    23. Cookie[] cookies = req.getCookies(); //这里返回数组,说明cookie可能存在多个(多个标志)。
    24. PrintWriter out = resp.getWriter();
    25. //我们为了要获取Cookie,首先要判断Cookie是否存在,这是一个正常的程序逻辑。
    26. //判断cookie是否存在
    27. if (cookies!=null){ //不等于null,说明cookie有值
    28. //如果存在cookie怎么办
    29. //如果存在我们要取出我们想取出的数据
    30. out.write("你上一次访问的时间是:");
    31. //进行遍历数据
    32. //两种for循环:
    33. //for(Cookie cookie:cookies){}
    34. //我们更倾向于使用下一种for循环(更加的灵活)
    35. for (int i=0;i
    36. Cookie cookie=cookies[i];
    37. //通过for循环进行遍历之后,我们拿到了每个cookie。
    38. //获取Cookie的名字
    39. //获取了cookie的名字之后,我们需要与服务器响应的Cookie进行对比。
    40. if(cookie.getName().equals("name")){
    41. URLDecoder.decode(cookie.getValue(),"UTF-8");
    42. //解码
    43. out.println(URLDecoder.decode(cookie.getValue(),"UTF-8"));
    44. }
    45. }
    46. //第一次访问一定是没有值的
    47. }else{
    48. out.write("这是您第一次访问本站");
    49. }
    50. //编码,有编码就要有解码
    51. Cookie cookie = new Cookie("name", URLEncoder.encode("蕾峰编程","utf-8"));
    52. resp.addCookie(cookie);
    53. }
    54. @Override
    55. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    56. doGet(req, resp);
    57. }
    58. }

    我们运行之后如下所示:

    发现成功进行了输出。 

  • 相关阅读:
    asp.net健身会所管理系统sqlserver
    基于改进萤火虫算法的图像分割的应用(Matlab代码实现)
    JNPF:让应用开发更简单、快捷
    SpringCloud(四) - 微信获取用户信息
    Scala入门到精通(尚硅谷学习笔记)章节一——scala入门
    MySQL中的DML操作
    并行计算技术与SIMD、SIMT
    MySQL 8.0 Clone Plugin 详解
    统一网关Gateway快速入门
    【每日一题Day344】LC2512奖励最顶尖的 K 名学生 | 哈希表+排序
  • 原文地址:https://blog.csdn.net/weixin_59448049/article/details/126689370