Cookie

1. 会话技术

  • 基本概念
    指⽤户开⼀个浏览器,访问⼀个⽹站,只要不关闭该浏览器,不管该⽤户点击多少个超链接,访问多少资源,直到⽤户关闭浏览器,整个这个过程我们称为⼀次会话。
  • 应用场景:
    1、在论坛登陆的时候,很多时候会有⼀个⼩框框问你是否要⾃动登陆,当你下次登陆的时候就不⽤输⼊密码了。
    2、根据我以前浏览过的商品,猜我喜欢什么商品
  • 会话跟踪技术有CookieSession

2. Cookie

2.1 什么是Cookie

  • ⽹⻚之间的交互是通过HTTP协议传输数据的,⽽Http协议是⽆状态的协议。⽆状态的协议是什么意思呢?⼀旦数据提交完后,浏览器和服务器的连接就会关闭,再次交互的时候需要重新建⽴新的连接。
  • 服务器⽆法确认⽤户的信息,于是乎,W3C就提出了:给每⼀个⽤户都发⼀个通⾏证,⽆论谁访问的时候都需要携带通⾏证,这样服务器就可以从通⾏证上确认⽤户的信息。通⾏证就是Cookie
  • Cookie的流程:浏览器访问服务器,如果服务器需要记录该⽤户的状态,就使⽤response向浏览器发送⼀个Cookie,浏览器会把Cookie保存起来。当浏览器再次访问服务器的时候,浏览器会把请求的⽹址连同Cookie⼀同交给服务器。
  • Cookie 是服务器通知客户端保存键值对的一种技术,客户端有了Cookie之后,每次请求都发送给服务器。每个Cookie大小都不超过4kb。

2.2 Cookie API

  • Cookie类⽤于创建⼀个Cookie对象
public Cookie(String name,String value)
  • response接⼝中定义了⼀个addCookie⽅法,它⽤于在其响应头中增加⼀个相应的Set-Cookie头字段
  • request接⼝中定义了⼀个getCookies⽅法,它⽤于获取客户端提交的Cookie。

2.3 Cookie 有效期

Cookie的有效期是通过setMaxAge()来设置的。

  • MaxAge为正数,浏览器会把Cookie写到硬盘中,只要还在MaxAge秒之前,登陆⽹站时该Cookie就有效【不论关闭了浏览器还是电脑】
  • MaxAge为负数,Cookie是临时性的,仅在本浏览器内有效,关闭浏览器Cookie就失效了,Cookie不会写到硬盘中。Cookie默认值就是-1,意味着没设置Cookie的有效期,在硬盘中就找不到对应的⽂件。
  • MaxAge为0,则表示删除该Cookie。Cookie机制没有提供删除Cookie的⽅法,把MaxAge设置为0等同于删除Cookie

3. Cookie 基本操作

3.1 创建 Cookie

  • Cookie保存英文
 // 创建Cookie对象,指定 名称 和 值
Cookie cookie = new Cookie("username","zouxiaopang");
// 设置Cookie时间
cookie.setMaxAge(1000);
// 向浏览器传送一个Cookie
response.addCookie(cookie);
response.getWriter().write("我已经向浏览器发送了一个Cookie");
  • cookie 保存中文
    中⽂属于Unicode字符,英⽂数据ASCII字符,中⽂占4个字符或者3个字符,英⽂占2个字符。解决:
    Cookie使⽤Unicode字符时需要对Unicode字符进⾏编码。
String pick = "小连";
Cookie cookie2 = new Cookie("pick", URLEncoder.encode(pick, "UTF-8"));
cookie2.setMaxAge(1000);
response.addCookie(cookie2);
response.getWriter().write("我已经向浏览器发送了一个Cookie");

在这里插入图片描述

3.2 获取Cookie

Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
    String name = cookies[i].getName();
    //经过URLEncoding就要URLDecoding
    String value = URLDecoder.decode(cookies[i].getValue(), "UTF-8");
    response.getWriter().write(name + "------" + value+"<br>");
}

在这里插入图片描述

3.3 Cookie的修改

Cookie存储的⽅式类似于Map集合,Cookie的名称相同,通过response添加到浏览器中,会覆盖原来的Cookie。

  • 以pick为例,改变该属性的值。
    – 原先 pick 值为 小连
    在这里插入图片描述
    – 后 pick 值为 小连、小天、小鬼
    在这里插入图片描述
pick = "小连、小天、小鬼";
cookie2 = new Cookie("pick", URLEncoder.encode(pick, "UTF-8"));
response.addCookie(cookie2);

3.4 Cookie 删除

删除Cookie,需要将MaxAge设置为0,并添加到浏览器中

String pick = "小连、小天、小鬼";
Cookie cookie = new Cookie("pick", URLEncoder.encode(pick,"UTF-8"));
cookie.setMaxAge(0);
response.addCookie(cookie);
response.getWriter().write("我删除了该cookie");

在这里插入图片描述

  • 注:删除,修改Cookie时,新建的Cookie除了value、maxAge之外的所有属性都要与原Cookie相 同。否则浏览器将视为不同的Cookie,不予覆盖,导致删除修改失败!

3.5 Cookie的域名

  • domain属性决定运⾏访问Cookie的域名。domain的值规定为.域名
  • Cookie的隐私安全机制决定Cookie是不可跨域名的。也就是说www.baidu.com和www.google.com之间的Cookie是互不交接的。即使是同⼀级域名,不同⼆级域名也不能交接,也就是说:www.goole.com和www.image.goole.com的Cookie也不能访问。
  • 在本地配置两个虚拟主机,详见Tomcat 6.临时域名
    在这里插入图片描述
<Engine name="Catalina" defaultHost="localhost">
	<Host name="www.zouxiaopang.com" appBase="E:\SpringMvc\servlet">    
		<Context path="/" docBase="E:\SpringMvc\out\artifacts\servlet_war_exploded" /> 
	</Host>
	<Host name="www.lian.zouxiaopang.com" appBase="E:\SpringMvc\servlet">    
		<Context path="/" docBase="E:\SpringMvc\out\artifacts\servlet_war_exploded" /> 
	</Host>
  1. 使用www.zouxiaopang.com域名发送了一个Cookie给浏览器
Cookie cookie = new Cookie("name","zouxiaopang");
cookie.setMaxAge(1000);
response.addCookie(cookie);
response.getWriter().write("使用www.zouxiaopang.com域名添加一个Cookie");

在这里插入图片描述

  1. 通过localhost:8080 和 www.lian.zouxiaopang.com是无法获取到www.zouxiaopang.com上传的Cookie。
    在这里插入图片描述在这里插入图片描述
  2. 要想⼀级域名相同的⽹⻚Cookie之间可以相互访问。也就是说www.lian.zouxiaopang.com可以获取到www.zouxiaopang.com的Cookie就需要使⽤到domain⽅法。
Cookie cookie = new Cookie("name","zouxiaopang");
cookie.setMaxAge(1000);
cookie.setDomain(".zouxiaopang.com");
response.addCookie(cookie);
response.getWriter().write("使用www.zouxiaopang.com域名添加一个Cookie,只要一级是zouxiaopang.com都可以访问");

在这里插入图片描述
在这里插入图片描述在这里插入图片描述


4. Cookie 应用

4.1 获取上次访问的时间

  • 每次登陆的时候,获取Cookie保存的值,在更新下Cookie的值。
  • 访问Servlet有两种情况:
    ① 第一次访问
    ② 已经访问过
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM--dd HH:mm:ss");
response.setContentType("text/html;charset=UTF-8");
PrintWriter printWriter = response.getWriter();
//获取网页上所有的Cookie
Cookie[] cookies = request.getCookies();
//判断cookie的值是否为空
String cookieValue = null;
for(int i = 0; cookies != null && i < cookies.length; i++){
    //获取到以time为名的Cookie
    if(cookies[i].getName().equals("time")){
        //获取上一次访问的时间
        cookieValue = cookies[i].getValue();
        printWriter.write("您上次访问的时间为:"+cookieValue);
        //修改这次访问的time值
        cookies[i].setValue(simpleDateFormat.format(new Date()));;
        response.addCookie(cookies[i]);
        break;
    }
}
// 如果cookieValue的值是空的,那么就是第一次访问
if(cookieValue == null){
    Cookie cookie = new Cookie("time",simpleDateFormat.format(new Date()));
    cookie.setMaxAge(20000);
    response.addCookie(cookie);
    printWriter.write("您是第一次登陆!!!");
}

请添加图片描述
请添加图片描述

4.2 显示上次浏览过得商品

以查看书籍为例,所有 servlet 创建在 good 包中。

  1. 设计 book 对象 (建议设为Book对象,由于取名失误,后创建对象,取名及其奇怪!)
    主要编写:属性,有参/无参构造器,各种get/set方法
package good;

public class book {
    private String id;
    private String name;
    private String author;
    public book() {
    }
    public book(String id, String name, String author) {
        this.id = id;
        this.name = name;
        this.author = author;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
}

  1. 设计⼀个简单的数据库存储数据。就⽤LinkedHashMap集合【根据商品的id找书籍所以⽤Map,删改较多所以⽤Linked】db.java
package good;

import java.util.LinkedHashMap;

public class db {
    private static LinkedHashMap<String,book> linkedHashMap = new LinkedHashMap<>();
	//简化开发复杂度,book的id和商品的id相同
    static{
        linkedHashMap.put("1", new book("1", "javaweb", "zou"));
        linkedHashMap.put("2", new book("2", "java", "xiao"));
        linkedHashMap.put("3", new book("3", "oracle", "pang"));
        linkedHashMap.put("4", new book("4", "mysql", "xiao"));
        linkedHashMap.put("5", new book("5", "ajax", "lian"));
    }
	//获取到所有书籍
    public static LinkedHashMap getAll(){
        return  linkedHashMap;
    }
}
  1. 显示⽹⻚上所有的书籍(show.java)
response.setContentType("text/html;charset=UTF-8");
PrintWriter printWriter = response.getWriter();

printWriter.write("所有书籍:<br/>");
//获取数据库所有的书
LinkedHashMap<String,book> linkedHashMap = db.getAll();
Set<Map.Entry<String,book>> entryset = linkedHashMap.entrySet();
//显示所有书到网页上
for(Map.Entry<String,book> entry : entryset){
    book books = entry.getValue();
    // 通过超链接的方式将书的id传递过去
    printWriter.write("<a href='/details?id="+books.getId()+"'target='_blank'> " + books.getName() + "</a>");
    printWriter.write("<br/>");
}
  1. 接收id,找到⽤户想要看哪⼀本书,输出该书的详细信息(details.java
//由于book的id和商品的id是⼀致的。获取到⽤户点击的书
String id = request.getParameter("id");
book books = (book) db.getAll().get(id);
//输出书的详细信息
printWriter.write("编号:" + books.getId()+"<br/>");
printWriter.write("书名:" + books.getName()+"<br/>");
printWriter.write("作者:" + books.getAuthor()+"<br/>");
  1. 传送Cookie,由于访问的书比较多,定义只能显示最近浏览过得三本书籍。在details.java文件中创建protected String makeHistory(HttpServletRequest request, String id)方法来获取Cookie内容。
  • 步骤一: 先遍历下Cookie,看下有没有我们想要的Cookie。如果找到想要的Cookie,那就取出Cookie的值。
  • 步骤二: 取出Cookie的值,有四种情况
    a. Cookie的值为null【直接把传⼊进来的id当做是Cookie的值】
    b. Cookie的值⻓度有3个了【把排在最后的id去掉,把传进来的id排在最前边】
    c. Cookie的值已经包含有传递进来的id了【把已经包含的id先去掉,再把id排在最前⾯】
    d. Cookie的值就只有1个或2个,直接把id排在最前边
  • 步骤三: 是把集合中的值取出来,拼接成⼀个字符串
// 步骤一:
String bookHistory = null;
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
    if (cookies[i].getName().equals("bookHistory")) {
        bookHistory = cookies[i].getValue();
    }
}
// 步骤二: 情况a
if (bookHistory == null) {
    return id;
}
// 步骤二: 情况bcd
//如果Cookie的值不是null的,那么就分解Cookie的得到之前的id。
String[] strings = bookHistory.split("\\_");
//为了增删容易并且还要判断id是否存在于该字符串内-----我们使⽤LinkedList集合装载分解出来id
List list = Arrays.asList(strings);
LinkedList<String> linkedList = new LinkedList<>();
linkedList.addAll(list);
if (linkedList.contains(id)) {
    linkedList.remove(id);
    linkedList.addFirst(id);
}else {
    if (linkedList.size() >= 3) {
        linkedList.removeLast();
        linkedList.addFirst(id);
    } else {
        linkedList.addFirst(id);
    }
}
// 步骤三:
StringBuffer stringBuffer = new StringBuffer();
//遍历LinkedList集合,添加个下划线“_”
for (String s : linkedList) {
    stringBuffer.append(s + "_");
}
//最后⼀个元素后⾯就不需要下划线了
return stringBuffer.deleteCharAt(stringBuffer.length() - 1).toString();
  1. 设置Cookie的⽣命周期,回送给浏览器即可(details.java
String bookHistory = makeHistory(request, id);
Cookie cookie = new Cookie("bookHistory", bookHistory);
cookie.setMaxAge(30000);
response.addCookie(cookie);
  1. 在show页面上获取Cookie的值,显示⽤户浏览过的商品
printWriter.write("您曾经浏览过的商品:<br/>");
//显示⽤户浏览过的商品
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
    if (cookies[i].getName().equals("bookHistory")) {
        //获取到的bookHistory是2_3_1之类的
        String bookHistory = cookies[i].getValue();
        //拆解成每⼀个id值
        String[] ids = bookHistory.split("\\_");
        //得到每⼀个id值
        for (String id: ids) {
            //通过id找到每⼀本书
            book books = linkedHashMap.get(id);
            printWriter.write(books.getName());
            printWriter.write("<br/>");
        }
        break;
    }
}

没有访问过任何页面
请添加图片描述访问javaweb,传cookie值为1
请添加图片描述
请添加图片描述访问mysql书籍,返回cookie值为4_1
请添加图片描述
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值