Cookie

细节

问题

  1. 一次可不可以发送多个Cookie?

  2. Cookie在浏览器中保存多长时间?

  3. Cookie能不能存中文?

  4. Cookie共享问题?

问题1

一次可以发送多个Cookie

例如demo3

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
package cn.itcast.cookie;

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;

/**
* Cookie快速入门
*/
public class demo3 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建Cookie
Cookie c1=new Cookie("msg","hello");
Cookie c2=new Cookie("name","51nd0re1");
//2.发送Coookie
response.addCookie(c1);
response.addCookie(c2);

}

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

再访问demo2
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
package cn.itcast.cookie;

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;


public class demo2 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//3.获取Cookie
Cookie[] cs = request.getCookies();
//遍历Cookie
if(cs!=null){
for (Cookie c : cs) {
String name = c.getName();
String value = c.getValue();
System.out.println(name +" : "+ value);
}
}
}

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

运行结果

1
2
3
4
JSESSIONID : B6EEFDF05B072898913A84B36CB94B1A
msg : hello
name : 51nd0re1
Phpstorm-d069594e : 0d583fa6-ad80-4735-a385-c10cee7ee32f

看到成功获取了两个Cookie

同时要说明的是,并不是只有访问demo2才会带着cookie,实际上访问demo1也会带着cookie,只是因为没有获取,所以控制台看不到而已

问题2

  • 默认情况下,当浏览器关闭后,Cookie数据被销毁,也就是存储到浏览器的内存中

  • 设置Cookie的生命周期,让它持久化存储

    • setMaxAge(int seconds)

      1. 正数:将Coookie数据写到硬盘的文件中,持久化存储,Cookie存活时间

      2. 负数:默认值,浏览器关闭清空

      3. 零:删除Cookie信息

demo4

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
package cn.itcast.cookie;

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;

/**
* Cookie快速入门
*/
public class demo4 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建Cookie
Cookie c1=new Cookie("msg","setMaxAge");
//2. 设置Cookie的存活时间
c1.setMaxAge(30); //将cookie持久化到硬盘,持久化30秒,30秒后自动删除cookie文件
//3.发送Coookie
response.addCookie(c1);
}

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

先访问demo4,再访问demo2,30秒内无论你重新开启浏览器,cookie都会获取到,30秒后再次访问demo2就获取不到了

运行结果

1
2
msg : setMaxAge
Phpstorm-d069594e : 0d583fa6-ad80-4735-a385-c10cee7ee32f

负数就是默认的,不演示了,零的操作也很简单,先设置一个持久化访问之后获取cookie,再重新设置为0,再次访问并获取

问题3

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

    • 需要将中文数据转码—一般采用URL编码(%E3),特殊字符不支持,建议使用URL编码存储,URL解码来解析
  • 在tomcat 8 之后 cookie支持中文数据

demo5

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
package cn.itcast.cookie;

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;

/**
* Cookie快速入门
*/
public class demo5 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建Cookie
Cookie c1=new Cookie("msg","你好");
//3.发送Coookie
response.addCookie(c1);
}

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

运行结果
1
2
msg : 你好
Phpstorm-d069594e : 0d583fa6-ad80-4735-a385-c10cee7ee32f

问题4

  • 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?

    • 默认情况下cookie不能共享

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

      • 如果要共享,则可以将path设置为”/“,代表根路径
  • 不同的tomcat服务器间cookie共享问题?

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

      • setDomain(“.baidu.com”),那么tieba.baidu.com和new.baidu.com中cookie可以共享
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
package cn.itcast.cookie;

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;

/**
* Cookie快速入门
*/
public class demo5 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建Cookie
Cookie c1=new Cookie("msg","你好");
//2. 设置cookie共享范围
c1.setPath("/");
//3.发送Coookie
response.addCookie(c1);
}

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

像这样的话,在同一个服务器下的模块都可以共享这个cookie

特点&作用

  1. cookie存储数据在客户端浏览器

  2. 浏览器对于单个cookie的大小有限制以及对同一域名下的总cookie数量也有限制

  • 作用:

    1. cookie一般用于存储少量的不太敏感的数据

    2. 在不登录的情况下,完成服务器对客户端的身份识别

案例

  1. 需求:

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

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

  2. 分析:

    1. 可以采用cookie来完成

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

      1. 有:不是第一次访问

      2. 没有:是第一次访问

        1. 响应数据:您好,欢迎首次访问

        2. 写回cookie:lastTime=时间

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package cn.itcast.cookie;

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.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
在服务器中的Servlet判断是否有一个名为lastTime的cookie
1. 有:不是第一次访问
1. 响应数据:欢迎回来,您上次访问时间为:时间
2. 没有:是第一次访问
1. 响应数据:您好,欢迎首次访问
2. 写回cookie:lastTime=时间
*/

public class CookieTest extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应的消息体的数据格式以及编码
response.setContentType("text/html;charset=utf-8");

//1.获取所有的cookie
Cookie[] cs = request.getCookies();
boolean flag=false; //没有cookie为false
//2.遍历cookie数组
if (cs!=null&&cs.length>0){
for (Cookie c : cs) {
//3.获取cookie的名称
String name = c.getName();
//4.判断名称是否是lastTime
if ("lastTime".equals(name)){
//有该cookie,不是第一次访问
flag=true;//有lastTime的cookie
//设置cookie的value
//获取当前时间的字符串,重新设置cookie的值,重新发送cookie
Date date=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String str_date = sdf.format(date);
System.out.println("编码前"+str_date);
//URL编码
str_date=URLEncoder.encode(str_date,"utf-8");
System.out.println("编码后"+str_date);
c.setValue(str_date);
//设置cookie的存活时间
c.setMaxAge(60*60*24*30);//一个月
response.addCookie(c);

//响应数据
//获取cookie的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 (cs==null || cs.length==0 || flag==false){
//没有,第一次访问

//设置cookie的value
//获取当前时间的字符串,重新设置cookie的值,重新发送cookie
Date date=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("YYYY年MM月dd日 HH:mm:ss");
String str_date = sdf.format(date);
System.out.println("编码前"+str_date);
//URL编码
str_date=URLEncoder.encode(str_date,"utf-8");
System.out.println("编码后"+str_date);

Cookie c=new Cookie("lastTime", str_date);
c.setValue(str_date);
//设置cookie的存活时间
c.setMaxAge(60*60*24*30);//一个月
response.addCookie(c);

response.getWriter().write("<h1>您好,欢迎首次访问</h1>");
}

}

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

首次运行
avatar

控制台结果

1
2
3
4
5
6
编码前2020080316:42:07
编码后2020%E5%B9%B408%E6%9C%8803%E6%97%A5+16%3A42%3A07
解码前2020%E5%B9%B408%E6%9C%8803%E6%97%A5+16%3A42%3A07
解码后2020080316:42:07
编码前2020080316:42:09
编码后2020%E5%B9%B408%E6%9C%8803%E6%97%A5+16%3A42%3A09

再次刷新一下
avatar

控制台结果

1
2
3
4
编码前2020080316:43:42
编码后2020%E5%B9%B408%E6%9C%8803%E6%97%A5+16%3A43%3A42
解码前2020%E5%B9%B408%E6%9C%8803%E6%97%A5+16%3A43%3A42
解码后2020080316:43:42