会话 —— Cookie

本文详细介绍了Cookie作为客户端会话技术的工作原理、API使用、发送与接收过程、存储时间、中文和特殊符号处理、共享问题以及其特点和作用。通过案例展示了如何利用Cookie记录浏览器访问时间。

目录

一、会话

  1. 会话:一次会话中包含多次请求和响应
    • 什么是一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开位置。
  2. 会话功能:在一次会话的范围内的多次请求间,共享数据。
  3. 方式:
    1. 客户端会话技术:Cookie
    2. 服务器端会话技术:Session

二、Cookie

2.1 API
1. 创建Cookie对象,绑定数据
Cookie(String name, String value);
2. 服务器端通过HttpServletResponse,发送Cookie到客户端
void addCookie(Cookie cookie);
3. 服务器端通过HttpServletRequest,获取Cookie,拿到数据(客户端再次访问服务器端资源时,会携带客户端保存的Cookie到服务器端。服务器端可以获取该Cookie)
Cookie[] getCookies();
2.2 发送和接收Cookie,演示代码

创建Demo1_Cookie发送Cookie,Demo2_Cookie2获取Cookie
Demo1_Cookie:

@WebServlet("/cookie1")
public class Demo1_Cookie extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
		1. 创建Cookie对象,绑定数据
			* Cookie(String name, String value);
		2. 服务器端通过HttpServletResponse,发送Cookie到客户端
			* void	 addCookie(Cookie cookie);
		3. 服务器端通过HttpServletRequest,获取Cookie,拿到数据(客户端再次访问服务器端资源时,会携带客户端保存的Cookie到服务器端。服务器端可以获取该Cookie)
			* Cookie[] getCookies();
        * */
        // 1. 创建Cookie对象,绑定数据
        Cookie cookie = new Cookie("msg", "Cookie的值");
        
        // 2. 发送Cookie到客户端
        response.addCookie(cookie);

        // 3. 创建Demo2_Cookie 获取Cookie

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

Demo2_Cookie2:

@WebServlet("/cookie2")
public class Demo2_Cookie extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
        3. 服务器端通过HttpServletRequest,获取Cookie,拿到数据(客户端再次访问服务器端资源时,会携带客户端保存的Cookie到服务器端。服务器端可以获取该Cookie)
        * */
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                String name = cookie.getName();
                String value = cookie.getValue();
                System.out.println("name=" + name + ",value=" + value);
            }
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

打开浏览器,先访问 cookie1,如下图,我们可以看到,响应头会携带cookie发送到客户端: set-cookie : key=value
在这里插入图片描述
然后在浏览器中,访问 cookie2,如下图,我们可以看到,客户端会在请求头中携带cookie到服务器端:cookie : key=value
在这里插入图片描述

2.3 Cookie实现原理

cookie实现原理

2.4 一次发送多个cookie
 // 1. 创建Cookie对象,绑定数据
 Cookie cookie1 = new Cookie("key1", "value1");
 Cookie cookie2 = new Cookie("key2", "value2");
 Cookie cookie3 = new Cookie("key3", "value3");


 // 2. 发送Cookie到客户端
 response.addCookie(cookie1);
 response.addCookie(cookie2);
 response.addCookie(cookie3);
2.5 在浏览器中存储时间
  1. 默认情况下,cookie保存在内存中,当浏览器关闭后,Cookie数据被销毁。
  2. 自定义存储方式
参数:expiry 秒
1. 正数:将cookie数据写到硬盘的文件中,即持久化存储。cookie存货时间。例如,expiry=30,那么30秒后,硬盘中的cookie会被删除。
2. 负数:默认值-1。cookie存储在浏览器的内存中,浏览器关闭后,cookie就会消失。
3. 0:删除cookie信息
public void setMaxAge(int expiry);
2.6 能否存中文和特殊符号
  1. tomcat8 之前,cookie不能存储中文数据:需要将中文数据转码。一般采用URL编码。
  2. tomcat8 之后,cookie支持存储中文。但是,对于特殊字符还是不支持(例如,空格),建议使用URL编码存储,使用URL解码解析。

URL编码:需要使用java.net包下的URLEncoder对value值进行编码,然后存储。
URL解码:使用URLDecoder对获取的value值进行解码。

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 有中文、空格这两种特殊符号
    String value = "阳光 明媚";
    System.out.println("编码前:" + value);

    /*------------URL编码--------------*/ 
    value = URLEncoder.encode(value, "utf-8");
    System.out.println("编码后:" + value);

    // 生成、发送cookie
    Cookie cookie = new Cookie("key", value);
    cookie.setMaxAge(3000);
    response.addCookie(cookie);

    /*------------URL解码--------------*/
    Cookie[] cookies = request.getCookies();
    if (cookies != null && cookies.length > 0) {
        for (Cookie c : cookies) {
            String name = c.getName();
            if ("key".equals(name)) {
                String cValue = c.getValue();
                System.out.println("解码前:" + cValue);
                
                // URL解码
                cValue = URLDecoder.decode(cValue, "utf-8");
                System.out.println("解码后:" + cValue);
            }
        }
    }
}
2.7 共享问题
  1. 同一个tomcat服务器中,部署了多个web项目,多个web项目之间cookie的共享问题:
    ① 默认情况下cookie是不能共享的;
    ② 设置cookie的获取范围,使用Cookie对象的setPath方法:
* 默认情况下,path是当前web项目的虚拟目录。
* 指定 path="/",则同一个tomcat服务器中的所有web项目可以共享cookie
public void setPath(String uri)
  1. 不同的tomcat服务器之间,cookie共享问题
public void setDomain(String pattern);

使用 setDomain 方法,如果多个服务器一级域名相同,那么 Cookie 可以共享。

例如:setDomain(".baidu.com"); 那么 tieba.baidu.com 服务器和 news.baidu.com 服务器之间可以共享Cookie。

2.8 特点
  1. Cookie存储数据在客户端浏览器。不安全,容易被篡改。
  2. 浏览器对于单个cookie的大小有限制(一般4kb),以及对同一个域名下的总cookie数量也有限制(20个以内)。
2.9 作用
  1. 存储少量的不太敏感的数据;
  2. 在不登录的情况下,来完成服务器对客户端的身份识别
2.10 案例:记录浏览器上一次访问时间,再次访问时显示

实现如下代码,然后在浏览器中访问该资源:

@WebServlet("/cookietest")
public class CookieTest extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置响应体数据格式和编码
        response.setContentType("text/html;charset=utf-8");
        /*
		案例需求:
			1. 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
			2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
        * */

        // 1. 获取所有cookie
        Cookie[] cookies = request.getCookies();
        boolean flag = false; // 未找到key=lasttime的cookie
        if (cookies != null && cookies.length > 0) {
            for (Cookie c : cookies) {
                // 获取cookie名称
                String name = c.getName();

                // 判断name是否是lasttime
                if ("lasttime".equals(name)) {
                    // 不是第一次访问
                    flag = true;

                    // 设置cookie的value
                    // 获取当前时间的字符串,修改cookie的值,重新发送cookie
                    Date date = new Date();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                    String formatDate = sdf.format(date);
                    System.out.println("编码前:" + formatDate);

                    // URL编码
                    formatDate = URLEncoder.encode(formatDate, "utf-8");
                    System.out.println("编码后:" + formatDate);


                    c.setValue(formatDate);
                    // 设置cookie存活时间为一个月
                    c.setMaxAge(30 * 24 * 3600);
                    response.addCookie(c);

                    // 响应数据,写出到页面
                    // 获取value
                    String value = c.getValue();

                    System.out.println("解码前:" + value);
                    // URL解码
                    value = URLDecoder.decode(value, "utf-8");
                    System.out.println("解码后:" + value);

                    response.getWriter().write("<h1>欢迎回来,您上次访问时间为:" + value + "</h1>");

                    break;
                }
            }
        }

        if (cookies == null || cookies.length == 0 || flag == false) {
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
            String formatDate = sdf.format(date);

            System.out.println("编码前:" + formatDate);

            // URL编码
            formatDate = URLEncoder.encode(formatDate, "utf-8");
            System.out.println("编码后:" + formatDate);

            Cookie cookie = new Cookie("lasttime", formatDate);
            // 设置cookie存活时间为一个月
            cookie.setMaxAge(30 * 24 * 3600);
            response.addCookie(cookie);

            // 响应数据,写出到页面
            response.getWriter().write("<h1>您好,欢迎您首次访问。</h1>");
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值