Cookie
今日目标
1. 会话概述
2. cookie【重点】
一 会话概述
1.1 什么是会话?
日常生活中:从拨通电话到挂断电话之间的一连串你问我答的过程就是一个会话。
B/S架构中:从浏览器第一次给服务器发送请求时,建立会话;直到有一方断开,会话结束。
一次会话:包含多次请求响应。
1.2 会话技术
问题:Http是一个无状态协议,同一个会话的连续两个请求相互独立,彼此并不了解
作用:用于存储浏览器与服务器在请求和响应过程中产生的数据
在一次会话中(多次请求响应), 共享数据
客户端会话技术:cookie
服务器端会话技术:session
二 Cookie【重点】
2.1 概述
Cookie是客户端的会话技术
Cookie作用:在一次会话的多次请求之间共享数据,将数据保存到客户端(浏览器)
# Cookie的特点
1. cookie保存在客户端(浏览器), 往往是由服务器产生发送给浏览器
2. cookie只能保存字符串, 格式是entry(name : value)
3. cookie的大小有限制: 4k
4. 一般, 同一域名下的cookie限制数量50个
当当购物车
# 以游客的身份访问亚马逊
1. 第一次访问亚马逊, 添加一个商品到购物车
2. 关闭亚马逊
3. 接着再次访问亚马逊, 发现该商品依然在购物车
# 分析数据特点
游客的数据价值不大
# 第一个方案: 存在服务端
1. Map存
1). 占服务器内存
2). 需要标记数据的归属, 不好标记
2. 数据库存
1). 占磁盘空间
2). 需要标记数据的归属
不推荐
# 第二个方案: 存在浏览器端
1). 不占用服务器存储空间
2). 不需要标记数据的归属
cookie
# 扩展: 如果是会员, 会话的购物车数据一般是保存在数据库
会员数据价值比较大
会员的数据直接用会员id标记可以
2.2 快速入门
1. 设置数据到cookie中
// 1.创建cookie对象,设置数据
Cookie cookie = new Cookie(String name,String value);
// 2.通过response,响应(返回)cookie
response.addCookie(cookie);
2. 从cookie中获取数据
// 1.通过request对象,接收cookie数组
Cookie[] cookies = request.getCookies();
// 2.遍历数组
获取name值: String name = cookie.getName();
获取value值: String value = cookie.getValue();
index.html
<a href="Cookie01Servlet">第一次访问亚马逊_添加商品到购物车</a> <br>
<a href="Cookie02Servlet">第二次访问亚马逊_查看购物车有数据</a> <br>
package com.itheima01.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/Cookie01Servlet")
public class Cookie01Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 接收请求
//2. 业务处理
//用cookie记录购物车数据
Cookie cookie = new Cookie("buycar", "huawei");
//3. 响应
//将cookie放在响应中发送给浏览器
response.addCookie(cookie);
}
}
package com.itheima01.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/Cookie02Servlet")
public class Cookie02Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//从请求中获取所有的cookie
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.println(name + "-" + value);
}
}
}
google浏览器中查看Cookie
2.3 工作原理
基于HTTP协议:
1. 服务器发送Cookie给浏览器是通过 : 响应(响应头 set-cookie)
Set-Cookie: phone=xiaomi
Set-Cookie: computer=lenovo
2. 浏览器发送Cookie给服务器是通过: 请求(请求头 cookie)
Cookie: phone=xiaomi; computer=lenovo
2.4 Cookie详情
2.4.1 服务器可以发送多个Cookie给浏览器吗?
* 答案: 可以的
// 1. 创建多个cookie对象
Cookie cookie1 = new Cookie("book","HighMath");
Cookie cookie2 = new Cookie("music","lifeyun");
// 2. 通过response响应多个
response.addCookie(cookie1);
response.addCookie(cookie2);
package com.itheima03.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("/Cookie01Servlet")
public class Cookie01Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 存数据到cookie中
Cookie cookie = new Cookie("book", "HighMath");
Cookie cookie2 = new Cookie("music", "lifeyun");
//2. 将cookie放到响应头,响应给浏览器
response.addCookie(cookie);
response.addCookie(cookie2);
}
}
2.4.2 Cookie是否可以存储中文和非法字符?
* tomcat8之前的版本,不支持中文
* tomcat8以后的版本,支持中文...
但是按照 Rfc6265Cookie规范,在cookie值中不能使用分号(;)、逗号(,)、等号(=)以及空格
我们可以存储,但是要使用url编码,来避开这个规范限制
* 解决
java.net.URLEncoder.encode(字符串","utf-8") 把字符串使用utf-8进行编码
java.net.URLDecoder.decode(字符串","utf-8") 把字符串使用utf-8进行解码
package com.itheima01.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;
import java.net.URLEncoder;
/*
TODO:
* tomcat8之前的版本,不支持中文
* tomcat8以后的版本,支持中文...
但是按照 Rfc6265Cookie规范,在cookie值中不能使用分号(;)、逗号(,)、等号(=)以及空格
我们可以存储,但是要使用url编码,来避开这个规范限制
* 解决
java.net.URLEncoder.encode(字符串","utf-8") 把字符串使用utf-8进行编码
java.net.URLDecoder.decode(字符串","utf-8") 把字符串使用utf-8进行解码
*/
@WebServlet("/Cookie03Servlet")
public class Cookie03Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 接收请求
//2. 业务处理
//用cookie记录购物车数据
String str = "华为 为";
//将utf-8编码的字符串进行url编码
// 华为 为 -> %E5%8D%8E%E4%B8%BA+%E4%B8%BA
// url编码 : 空格 转换成 +
str = URLEncoder.encode(str,"utf-8");
Cookie cookie = new Cookie("phone", str);
//3. 响应
//将cookie放在响应中发送给浏览器
response.addCookie(cookie);
}
}
package com.itheima01.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;
import java.net.URLDecoder;
@WebServlet("/Cookie04Servlet")
public class Cookie04Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//从请求中获取所有的cookie
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
String name = cookie.getName();
String value = cookie.getValue();
if("phone".equals(name)){
//将value进行url解码(用utf-8)
value = URLDecoder.decode(value,"utf-8");
}
System.out.println(name + "-" + value);
}
}
}
2.4.3 Cookie的域名作用(domain)
1. cookie信息中的域名作用是标记这个cookie的归属
在我们的浏览器中,既保存了域名为localhost的cookie,又保存域名为baidu的cookie
那么访问的网站如果是 http://localhost:8080, 浏览器的请求只会携带域名为localhost的cookie
2. 默认情况下,cookie的域名 和 发送此cookie的服务器域名是一致的
url格式 -> 协议://域名:端口/资源位置
2.4.4 Cookie的路径作用(path)
# url格式
协议://ip:port/资源位置?参数
1). 资源位置 -> /项目虚拟路径/项目中的资源路径
2). 参数 -> name=value&name=value...
http://localhost:8080/day17/Cookie04Servlet
0. 在我们的项目中,cookie的路径默认为项目的虚拟路径
项目虚拟路径为 /day17
1. 第一个作用: cookie信息中的path和name共同决定了cookie的唯一性
a. Servlet被浏览器每访问一次, cookie就会发送一次
b. 如果服务器再次发送一个同 path+name的cookie,会覆盖浏览器的那个cookie
(新覆盖旧)
c. 服务器再次发送一个同 path, 异name的cookie , 不会覆盖
d. 服务器再次发送一个异path, 同name的cookie, 不会覆盖
2. 第二个作用: cookie的path还决定了cookie允许被访问的范围(有效路径)
0). 浏览器访问的服务器资源路径跟cookie的路径相同,或者是cookie路径的子路径,才会携带这个cookie到服务器
1). 例子
I. 有两个cookie
name=music,path=/day17
name=book,path=/day17/abc
II. 浏览器访问X网址,携带Y cookie
当 X = http://localhost:8080/day17
Y = music
当 X = http://localhost:8080/day17/abc/d
Y = music,book
当 X = http://localhost:8080/day17/aaa
Y = music
2). 理解
当 cookie.path = Z的时候, 只有访问Z以及Z的子路径才允许携带cookie(cookie才允许被服务器访问)
3). 运用场景
https://www.baidu.com:443/map : 地图
cookie.path = /map
https://www.baidu.com:443/wenku : 文库
/wenku
访问文库,不会携带地图模块的cookie,实际也没必要
#API : cookie.setPath(虚拟路径);
路径要以 / 开头
package com.itheima01.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/Cookie01Servlet")
public class Cookie01Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 接收请求
//2. 业务处理
//用cookie记录购物车数据
Cookie cookie = new Cookie("music", "oppo");
Cookie cookie2 = new Cookie("book", "lenovo");
//3. 响应
//将cookie放在响应中发送给浏览器
// cookie.setPath("默认当前项目虚拟路径"); // -> /day17
cookie2.setPath("/day17/abc");
response.addCookie(cookie);
response.addCookie(cookie2);
}
}
2.4.5 Cookie的存活时间
# 浏览器中cookie的信息
1. 创建时间: 浏览器接收到此cookie的时间
2. 到期时间: cookie销毁的时间
# cookie的存活时间有两种
1. 会话级别 (默认)
浏览器关闭 : cookie会自动销毁
2. 持久级别(需要手动设置)
cookie.setMaxAge(int second);
正数:指定存活时间,单位是秒
零:立即销毁
package com.itheima03.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("/Cookie01Servlet")
public class Cookie01Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 存数据到cookie中
Cookie cookie = new Cookie("book", "HighMath");
Cookie cookie2 = new Cookie("music", "lifeyun");
cookie.setMaxAge(60*30); // 30分钟 ,单位是秒
//2. 将cookie放到响应头,响应给浏览器
response.addCookie(cookie);
response.addCookie(cookie2);
}
}
2.4.6 Cookie的删除
# 目标:删除Cookie
1. 用户在浏览器中手动删除cookie(清除浏览记录): 用户未必知道或者配合
2. 从服务端远程操控删除cookie(服务端)
# 远程删除实现步骤:
0. 核心思想: 服务端发送一个跟目标cookie同 path+name的cookie,此cookie的存活时间为0
原理: 新cookie先覆盖浏览器保存的cookie,但是因为时间为0,新cookie马上死掉
package com.itheima01.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("/Cookie05Servlet")
public class Cookie05Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 核心思想: 服务端发送一个跟目标cookie同 path+name的cookie,此cookie的存活时间为0
// 原理: 新cookie先覆盖浏览器保存的cookie,但是因为时间为0,新cookie马上死掉
Cookie cookie = new Cookie("music", "");
cookie.setPath("/day17"); //默认项目虚拟路径
cookie.setMaxAge(0); // 立即销毁
response.addCookie(cookie);
}
}
2.5 Cookie特点
1. cookie存储数据在客户端(浏览器)
2. cookie的存储数据(name和value)只能是字符串
3. cookie单个大小不能超过4KB
4. 同一个域名下cookie数量一般不能超过50个
5. 同一域名下, cookie的path和name决定了它的唯一性
6. cookie存储的数据不太安全
信息保存在用户的电脑上,都相对不安全