一、Cookie是什么?
Cookie翻译成中文是小甜点,小饼干的意思。在HTTP中它表示服务器发送给客户端浏览器的小甜点。其实Cookie就是一个键和值构成的,随着服务器端的响应发送给客户端浏览器,然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器的时候会把Cookie再发送给服务器
二、Cookie规范
你大可以放心,Cookie不会占满你的磁盘。因为一个Cookie最多只有4kb,一个服务器最多只能发送客户端20个Cookie,并且浏览器最多可以保存300个Cookie。当然,在浏览器大战的今天,一些浏览器为了打败对手,可能会对Cookie规范“扩展”了一些,例如每个Cookie的大小为8KB,最多可保存500个Cookie等!但也不会出现把你磁盘占满的可能!
不同的浏览器之间不能共享Cookie!!!
三、Cookie的作用
Cookie的作用可大了,但无论怎么夸大Cookie的作用都离不开“跟踪客户端状态”这句话。我们知道Cookie是服务器保存在客户端的信息,然后客户端会在下次你请求把Cookie在还给服务器,这样服务器就可以通过信息来识别客户端了。
就好比你去医院看病,第一次去要买病例,然后你去任何科室都需要你出示卡片。只要你出示卡片,医生就会知道你去过哪些科室,看了哪些病!卡片上只有一个ID,它就是Cookie,而你本人就是客户端,而医生就是服务器了。
四、Cookie的属性
Cookie最重要的4个属性:名字(name)、值(value)、路径(path)和域(domain)。
我们现在只需要关心name和value,而path和domain可以先不去了解!但后面也会去讲解它的作用。
javax.servlet.http.Cookie类只有一个构造器:Cookie(String name,String value)。你应该知道怎么创建一个Cookie对象:Cookie c = new Cookie("id","1");
五、保存Cookie到客户端
保存Cookie到客户端,这是响应工作的一部分,所有这个方法时response对象的。并且Cookie是HTTP协议的内容,所以保存Cookie是HttpServletResponse类的方法。
public void addCookie(Cookie c) 添加Cookie对象到当前到response对象
上面的方法可以被调用多次,从而完成添加多个Cookie对象到response中。
package cn.cookie;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 添加Cookie到客户端 */@SuppressWarnings("serial")public class CookieDemo1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie c = new Cookie("id", "1"); response.addCookie(c); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }}
使用浏览器访问
当再次访问的时候,查看请求头信息是否存在Cookie这个头信息。
六、Cookie的生命周期
Cookie会在客户端存活多久呢?这就是Cookie的生命了。默认情况下,Cookie只在浏览器的内存中存活,也就是说,当你关闭浏览器后,Cookie就会消失(也称为会话级Cookie)。
可以使用cookie.setMaxAge(int expiry)来设置Cookie的存活时间。参数expiry表示Cookie存活的秒数。
public void setMaxAge(60*60)
表示你Cookie对象可存活1小时。就算关闭浏览器,就算重启客户端电脑,Cookie也会存活1小时。因为当MaxAge大于0的时候,浏览器不仅会把cookie保存在浏览器内存中,还会把cookie的硬盘中。
public void setMaxAge(-1)
cookie的MaxAge属性的默认值就是-1:表示只在浏览器的内存中存活。一旦关闭浏览器窗口,那么cookie就会消失。
public void setMaxAge(0)
cookie被作废!表示cookie不在内存中存活,也不在硬盘上存活,这样的cookie的设置的目的就只有一个,那就是覆盖客户端原来的这个cookie,使其作废。
七、服务端读取Cookie
我们现在已经可以保存Cookie到客户端了,但是我们还不知道怎么让服务器获取Cookie。
如果浏览器保存了Cookie,那么会在下一次请求时候会把Cookie放到请求头中发送给服务器中, 这是服务器只需要在请求中读取Cookie,既然是在请求中读取Cookie,那么当然是使用request对象读取了。
public Cookie[] getCookies()
【注意】上面的方法返回的是Cookie数组,而不是一个Cookie对象。如果请求中没有Cookie,那么该方法返回null。
package cn.cookie;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 服务器端获取Cookie * @author Administrator * */@SuppressWarnings("serial")public class CookieDemo extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); //获取当前请求中的所有Cookie对象 Cookie[] cookies = request.getCookies(); //如果返回的数组不为null if(cookies != null){ //循环遍历,得到每一个Cookie对象 for (Cookie cookie : cookies) { //获取Cookie的名称 String name = cookie.getName(); //获取Cookie的值 String value = cookie.getValue(); response.getWriter().print(name+","+value); } } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }}
八、Cookie的路径
Cookie路径会影响请求中是否包含Cookie。
Cookie还有一个path属性,可以通过Cookie的setPath(String path)方法来设置。
也就是说,就算你不设置Cookie的path路径,Cookie也是有路径的,这个路径就是请求的路径。例如在请求
例如请求的路径是
到现在为止我们还没说过Cookie的path有什么用,现在我们来聊聊path的作用。首先声明一点,path不是指Cookie在客户端存放的路径!!!不同的浏览器存放Cookie的路径是不同的!!你不能通过Cookie的path来指定Cookie文件的存放路径!!!
那么,Cookie的path是干什么的呢?假设当前的浏览器已经有两个Cookie:
c1:name=id;value=haha;path=/day09/c2:name=name;value=hehe;path=/day09/serlvet/
当访问。
当访问
也就是说,在访问子路径的时候,会包含其父路径的Cookie,而在访问父路径的时候,不包含子路径的Cookie。
如果你想在BServlet中设置的Cookie,在客户端访问AServlet的时候也包含在请求头中,那么就需要设置BServlet中的path。
c2.setPath("/day09/");硬编码
c2.setPath(request.getContextPath()+"/");软编码
这样就可以设置Cookie的路径,保存在访问AServlet的时候,也会包含BServlet中添加的Cookie。
九、Cookie中的域名(不重要)
十、Cookie中保存中文
Cookie中是不可以设置中文的,但可以使用URLEncoder.encode()方法编码后再保存到Cookie中。在获取Cookie的时候,需要先使用URLDecoder.decode()方法解码,再使用。
package cn.cookie;import java.io.IOException;import java.net.URLDecoder;import java.net.URLEncoder;import javax.servlet.ServletException;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@SuppressWarnings("serial")public class CookieDemo3 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //向客户端添加Cookie String name = URLEncoder.encode("姓名","utf-8"); String value = URLEncoder.encode("张三","utf-8"); Cookie c = new Cookie(name, value); c.setMaxAge(60 * 60); response.addCookie(c); //从客户端请求中获取Cookie response.setContentType("text/html;charset=utf-8"); Cookie[] cookies = request.getCookies(); if(cookies != null){ for (Cookie cookie : cookies) { String cookieName = URLDecoder.decode(cookie.getName(), "utf-8"); String cookieValue = URLDecoder.decode(cookie.getValue(), "utf-8"); response.getWriter().println(cookieName+","+cookieValue); } } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }}
总结:
Cookie是客户端技术,程序把每个用户的数据以Cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源的时候,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。
案例:记录上次访问时间
package cn.cookie;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import javax.servlet.ServletException;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@SuppressWarnings("serial")public class ReadLastTime extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置响应的编码 response.setContentType("text/html;charset=utf-8"); //从客户端获取所有的Cookie Cookie[] cookies = request.getCookies(); //如果cookies == null,表示第一次登陆啊, if(cookies == null){ response.getWriter().println("亲,欢饮访问本系统"); }else{//不是第一次登陆 for (Cookie cookie : cookies) { if(cookie.getName().equals("last")){//如果cookie的key是last,就说明是本系统的设置的cookie response.getWriter().print("你上次访问的时间是"+cookie.getValue()); } } } //回写cookie到客户端 response.addCookie(new Cookie("last", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()))); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }}
案例:访问商品的浏览信息
productList.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><%=basePath%>"> My JSP 'productList.jsp' starting page
Product.java
package cn.cookie;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** *浏览商品记录 */@SuppressWarnings("serial")public class Product extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /** *1.获取请求参数 *2.获取Cookie数组,通过指定的名称,查找Cookie, *3.如果Cookie是 空,是第一次访问, * 创建Cookie,回写到浏览器 *4.如果Cookie不是null,不是第一次访问 * 说明了Cookie中存在了id * 判断当前的id,是否已经存在Cookie的value中? * 如果存在,不用操作 * 如果不存在,在后面追加product=1,2 *5.重定向商品列表页面 */ //获取请求参数 目的是:存放到Cookie中 String id = request.getParameter("id"); //获取所有的Cookie,查找指定名称的Cookie Cookie[] cookies = request.getCookies(); //查找指定名称的cookie Cookie cookie = getCookieByName(cookies,"product"); //如果Cookie=null,说明是第一次访问 if(cookie == null){ Cookie c = new Cookie("product", id); c.setMaxAge(60 * 60 * 24 *7); response.addCookie(c); }else{ //如果Cookie中不存在Id //获取Cookie的value(value=1,2,3) String value = cookie.getValue(); //判断,当前商品的id是否在cookie中 String[] values = value.split(","); //判断ID是否在value[]数组中 if(!checkId(values,id)){ cookie.setValue(value+","+id); cookie.setMaxAge(60 * 60 * 24 *7); response.addCookie(cookie); } } //重定向到商品展示页面 response.sendRedirect("/day11/cookie/productList.jsp"); } /** * 判断,当前的id是否包含在value数组中 * @param values * @param value * @return */ private boolean checkId(String[] values, String value) { for (String string : values) { if(value.equals(string)){ return true; } } return false; } /** * 根据指定的名称查找Cookie * @param cookies * @param string * @return */ private Cookie getCookieByName(Cookie[] cookies, String string) { //表示第一次访问 if(cookies == null){ return null; }else{ //遍历Cookie[],拿到指定名称的Cookie for (Cookie cookie : cookies) { if(cookie.getName().equals(string)){ return cookie; } } } return null; } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }}
ClearProduct.java
package cn.cookie;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@SuppressWarnings("serial")public class ClearProduct extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie c = new Cookie("product", ""); c.setMaxAge(0); response.addCookie(c); response.sendRedirect("/day11/cookie/productList.jsp"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }}