Cookie 学习笔记

会话技术

  1. 概述

    • 会话是浏览器和服务器之间的多次请求和响应。
    • 也就是说,从浏览器访问服务器开始,到访问服务器结束浏览器关闭为止的这段时间内容产生的多次请求和响应,合起来叫做浏览器和服务器之间的一次会话。
  2. 功能

    • 实际上会话问题解决的还是客户端与服务器之间的通信问题,通过一些会话技术,可以将每个用户的数据以例如cookie/session的形式存储,方便以后用户访问web资源的时候使用

    • 例如:

      假定场景:A和B两人在某个网上购物商场登陆账号后,A买了一个HHKB的键盘,而B则购买了一把民谣吉他,这些信息都会被保存下来
      
      用途是:保存账户信息,登录时询问日后是否自动登录,或者根据之前浏览,购买过的商品,分析用户喜欢什么类型的商品,做出精准推送
      
  3. 会话维持的方式

    • 客户端会话技术:Cookie
    • 服务器端会话技术:Session

  1. 使用步骤

    1. 创建Cookie对象,绑定数据

      new Cookie(String name, String value)
      
    2. 发送Cookie对象

      response.addCookie(Cookie cookie) 
      
    3. 获取Cookie,拿到数据

      Cookie[]  request.getCookies()
      
  2. 实现

    1. 创建一个类,用来将数据绑定到Cookie对象上

      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;
      
      @WebServlet("/cookieDemo01")
      public class CookieDemo01 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
                  ServletException, IOException {
              // 创建 Cookie 对象
              Cookie cookie = new Cookie("massage", "HelloCookie");
              // 发送 Cookie
              response.addCookie(cookie);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
                  ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
    2. 创建一个类,用来获取Cookie对象中绑定到的数据

      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;
      
      @WebServlet("/cookieDemo02")
      public class CookieDemo02 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
                  ServletException, IOException {
              // 获取 Cookie
              Cookie[] cookies = request.getCookies();
              if (cookies != null) {
                  for (Cookie cookie : cookies) {
                      System.out.println(cookie.getName() + ":" + cookie.getValue());
                  }
              }
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
                  ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
    3. 启动服务器,浏览器访问:http://localhost:8080/CookieStudy_war_exploded/cookieDemo01,绑定数据到Cookie对象

    4. 然后再访问:http://localhost:8080/CookieStudy_war_exploded/cookieDemo02,控制台输出:

      20200529010410

  1. 概述:

    Cookies 可以简单的理解为服务器暂存在你浏览器中的一些信息文件,它将你在网站上所输入的一些内容,或者一些选项记录下来,当下一次你访问同一个网站的时候,服务器就会主动去查询这个cookie资料,如果存在的话,将会根据其中的内容,提供一些特别的功能,例如记住账号密码等。

  2. 具体流程

    浏览器访问服务器,如果服务器需要记录该用户的状态,就用response向浏览器发送一个cookie,浏览器会把Cookie保存起来。当浏览器再次访问服务器的时候,浏览器会把请求的网址以及Cookie一同提交给服务器。


创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。

举例:

  1. 创建一个类,用来将数据绑定到Cookie对象上

    @WebServlet("/cookieDemo03")
    public class CookieDemo03 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) {
            // 创建 Cookie 对象
            Cookie cookie1 = new Cookie("massage1", "HelloCookie1");
            Cookie cookie2 = new Cookie("massage2", "HelloCookie2");
            // 发送 Cookie
            response.addCookie(cookie1);
            response.addCookie(cookie2);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) {
            this.doGet(request, response);
        }
    }
    
  2. 创建一个类,用来获取Cookie对象中绑定到的数据

    @WebServlet("/cookieDemo04")
    public class CookieDemo04 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) {
            // 获取 Cookie
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    System.out.println(cookie.getName() + ":" + cookie.getValue());
                }
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) {
            this.doGet(request, response);
        }
    }
    
  3. 启动服务器,浏览器访问:http://localhost:8080/CookieStudy_war_exploded/cookieDemo03,绑定数据到Cookie对象

    20200529014453
  4. 然后再访问:http://localhost:8080/CookieStudy_war_exploded/cookieDemo02

    1. 控制台输出:

      20200529014612
  1. 默认情况下,当浏览器关闭后,Cookie数据被销毁

  2. 不过我们可以将Cookie存储到硬盘中,实现持久化存储

    方法:

    setMaxAge(int seconds)
    
    • seconds 为正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
    • seconds 为负数:当浏览器关闭后,Cookie数据被销毁(默认值)
    • seconds 为零:删除cookie信息
  3. 就用上面 一次发送多个 Cookie 的例子。当我们访问 /cookieDemo03 后,再访问 /cookieDemo04,这个时候cookie是还没有没销毁的,因为我们没有关闭浏览器(Cookie存在内存中)。一旦我们关闭浏览器(释放内存)之前的cookie就会被删除。那么我们这时候,不去访问 /cookieDemo03 ,直接去访问 /cookieDemo04 ,控制台是不会输出 CookieDemo03.java 对应的 cookie 绑定到的数据的。假如想要cookie的有效时间更长,可以通过在绑定数据到Cookie对象的时候,设置Cookie可以存在硬盘中的时间。

    如:

    @WebServlet("/cookieDemo05")
    public class CookieDemo05 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) {
            // 创建 Cookie 对象
            Cookie cookie = new Cookie("massage", "HelloCookie");
            // 设置 Cookie 的存在时间(实现 Cookie 的持久化存储)
            cookie.setMaxAge(30);
            // 发送 Cookie
            response.addCookie(cookie);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) {
            this.doGet(request, response);
        }
    }
    

  1. 在tomcat 8 之前 cookie中不能直接存储中文数据。

    需要将中文数据转码---一般采用URL编码(如:%E3)

  2. 在tomcat 8 之后,cookie支持中文数据。

    特殊字符还是不支持,建议使用URL编码存储,URL解码解析


假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中 cookie 默认情况下是不能共享的。

可以通过设置,来实现在同一个tomcat服务器、不同web项目中的 cookie 共享。

setPath(String path)
// 设置cookie的获取范围。默认情况下,设置当前的虚拟目录

如:/CookieStudy01_war_exploded 项目虚拟路径和 /CookieStudy02_war_exploded项目虚拟路径,他们的cookie是不能共享的,如果想要实现共享,可以设置cookie的虚拟目录为这两个虚拟目录的公共目录(这里的是:/

不同的tomcat服务器间cookie共享问题(了解)

setDomain(String path)
// 如果设置一级域名相同,那么多个服务器之间 cookie 可以共享

// 举例如:setDomain(".baidu.com"),那么 tieba.baidu.com 和 news.baidu.com 中 cookie 可以共享
  1. cookie 存储数据在客户端浏览器
  2. 浏览器对于单个 cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)
  3. cookie一般用于存出少量的不太敏感的数据。
  4. 在不登录的情况下,完成服务器对客户端的身份识别。

  1. 需求:记住用户上一次访问时间

    1. 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。

    2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串

  2. 分析:

    • 在服务器中的Servlet判断是否有一个名为lastTime的cookie

      • 用户不是第一次访问

        1. 响应数据:欢迎回来,您上次访问时间为:20XX年XX月XX日XX:XX:XX
        2. 写回Cookie当前访问时间:lastTime=20XX年XX月XX日XX:XX:XX
      • 用户是第一次访问

        1. 响应数据:您好,欢迎您首次访问
        2. 写回Cookie当前访问时间:lastTime=20XX年XX月XX日XX:XX:XX
  3. 实现:

    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;
    import java.net.URLDecoder;
    import java.net.URLEncoder;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    @WebServlet("/cookieTest")
    public class CookieTest extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws IOException {
            // 设置响应的消息体的数据格式以及编码
            response.setContentType("text/html;charset=utf-8");
            // 获取所有Cookie
            Cookie[] cookies = request.getCookies();
            // 默认没有cookie为lastTime
            boolean flag = false;
            // 遍历cookie数组
            if(cookies != null && cookies.length > 0) {
                for (Cookie cookie : cookies) {
                    // 获取cookie的名称
                    String name = cookie.getName();
                    // 判断名称是否是:lastTime
                    if("lastTime".equals(name)) {
                        // 有cookie为lastTime,不是第一次访问
                        flag = true;
                        // 获取当前时间的字符串
                        Date date  = new Date();
                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                        String stringDate = simpleDateFormat.format(date);
                        // 由于stringDate字符串中存在特殊字符(空格),需要URL编码
                        String encodeCookie = URLEncoder.encode(stringDate, "utf-8");
                        // 重新设置Cookie的值
                        cookie.setValue(encodeCookie);
                        // 设置cookie的存活时间:存活一个小时
                        cookie.setMaxAge(60 * 60);
                        // 在响应对象中添加该设置的cookie
                        response.addCookie(cookie);
    
                        // 响应数据
                        // 获取Cookie的value(时间)
                        String value = cookie.getValue();
                        // 对获取到的cookie值进行URL解码
                        String decodeValue = URLDecoder.decode(value, "utf-8");
                        response.getWriter().write("<h1>欢迎回来,您上次访问时间为:" + decodeValue + "</h1>");
                        // 已经完成了需求
                        break;
                    }
                }
            }
            // 假如上面遍历了所有的cookie,都没有cookie为lastTime,或者用户的请求中没有cookie,说明用户是第一次访问
            if(cookies == null || cookies.length == 0 || flag == false) {
                // 获取当前时间的字符串
                Date date  = new Date();
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                String stringDate = simpleDateFormat.format(date);
                // 由于stringDate字符串中存在特殊字符(空格),需要URL编码
                stringDate = URLEncoder.encode(stringDate, "utf-8");
                // 重新设置Cookie的值
                Cookie cookie = new Cookie("lastTime", stringDate);
                // 设置cookie的存活时间
                cookie.setMaxAge(60 * 60);
                // 重新发送cookie
                response.addCookie(cookie);
                response.getWriter().write("<h1>您好,欢迎您首次访问!</h1>");
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws IOException {
            this.doGet(request, response);
        }
    }
    
  4. 启动服务器,首次访问:http://localhost:8080/CookieStudy_war_exploded/cookieTest

    20200529230149
  5. 再次访问:http://localhost:8080/CookieStudy_war_exploded/cookieTest

    20200529230334

参考文献

  1. 会话技术——Cookies和Session详解
posted @ 2021-03-04 10:30  LeeHua  阅读(158)  评论(0编辑  收藏  举报