一.What is Cookie
我们在浏览器中,经常涉及到数据的交换,比如你登录邮箱,登录一个页面。我们经常会在此时设置30天内记住我,或者自动登录选项。那么它们是怎么记录信息的呢,答案就是今天的主角cookie了,Cookie是由HTTP服务器设置的,保存在浏览器中,但HTTP协议是一种无状态协议,在数据交换完毕后,服务器端和客户端的链接就会关闭,每次交换数据都需要建立新的链接。就像我们去超市买东西,没有积分卡的情况下,我们买完东西之后,超市没有我们的任何消费信息,但我们办了积分卡之后,超市就有了我们的消费信息。cookie就像是积分卡,可以保存积分,商品就是我们的信息,超市的系统就像服务器后台,http协议就是交易的过程。
Cookie的作用是储存在用户本地终端上的数据,也可以叫做浏览器缓存。
二.Cookie机制
Cookie信息则存放在HTTP请求头(Request Header)里。有了Cookie这样的技术实现,服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的Cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。
如果你把Cookies看成为http协议的一个扩展的话,理解起来就容易的多了,其实本质上cookies就是http的一个扩展。有两个http头部是专门负责设置以及发送cookie的,它们分别是Set-Cookie以及Cookie。当服务器返回给客户端一个http响应信息时,其中如果包含Set-Cookie这个头部时,意思就是指示客户端建立一个cookie,并且在后续的http请求中自动发送这个cookie到服务器端,直到这个cookie过期。一个cookie的设置以及发送过程分为以下四步:
客户端发送一个http请求到服务器端 服务器端发送一个http响应到客户端,其中包含Set-Cookie头部 客户端发送一个http请求到服务器端,其中包含Cookie头部 服务器端发送一个http响应到客户端。
这个通讯过程也可以用以下下示意图来描述:
在客户端的第二次请求中包含的Cookie头部中,提供给了服务器端可以用来唯一标识客户端身份的信息。这时,服务器端也就可以判断客户端是否启用了cookies。
三.Cookie的原理
由于HTTP是一种无状态的协议,服务器脚本向浏览器发送一组 Cookie。例如:姓名、年龄或识别号码等。浏览器将这些信息存储在本地计算机上,以备将来使用。当下一次浏览器向 Web 服务器发送任何请求时,浏览器会把这些 Cookie 信息发送到服务器,服务器将使用这些信息来识别用户。这就是Cookie的工作原理。
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
查看某个网站颁发的Cookie很简单。在浏览器地址栏输入javascript:alert (document. cookie)就可以了(需要有网才能查看)。JavaScript脚本会弹出一个对话框显示本网站颁发的所有Cookie的内容。Cookie的信息是可以加密的,比如baidu等。
注意:Cookie功能需要浏览器的支持。如果浏览器不支持Cookie(如大部分手机中的浏览器)或者把Cookie禁用了,Cookie功能就会失效。不同的浏览器采用不同的方式保存Cookie。IE浏览器会在“C:\Documents and Settings\你的用户名\Cookies”文件夹下以文本文件形式保存,一个文本文件保存一个Cookie。
四.Cookie的分类
cookie分为会话cookie和持久cookie,会话cookie是指在在不设定它的生命周期expires时的状态,前面说了,浏览器的开启到关闭就是一次会话,当关闭浏览器时,会话cookie就会跟随浏览器而销毁。当关闭一个页面时,不影响会话cookie的销毁。会话cookie就像我们没有办理积分卡时,单一的买卖过程,离开之后,信息则销毁。如果cookie的生存时间是整个会话期间的话,那么浏览器会将cookie保存在内存中,浏览器关闭时就会自动清除这个cookie。
持久cookie则是设定了它的生命周期expires,此时,cookie像商品一样,有个保质期,关闭浏览器之后,它不会销毁,直到设定的过期时间。对于持久cookie,可以在同一个浏览器中传递数据,比如,你在打开一个淘宝页面登陆后,你在点开一个商品页面,依然是登录状态,即便你关闭了浏览器,再次开启浏览器,依然会是登录状态。这就是因为cookie自动将数据传送到服务器端,在反馈回来的结果。持久cookie就像是我们办理了一张积分卡,即便离开,信息一直保留,直到时间到期,信息销毁。另外一种情况就是保存在客户端的硬盘中,浏览器关闭的话,该cookie也不会被清除,下次打开浏览器访问对应网站时,这个cookie就会自动再次发送到服务器端。
五.Cookie和Session的区别
在程序中,会话跟踪是很重要的事情。理论上,一个用户的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆。
1、Cookie机制是在客户端保持状态的方案,又叫会话跟踪机制。Session机制采用的是在服务器端保持状态的方案。
两者都是打开一次浏览器到关闭浏览器算是一次会话结束。
2、Cookie数据存放在客户的浏览器上,Session数据放在服务器上。
3、Cookie不是很安全,别人可以分析存放在本地的Cookie并进行Cookie欺骗,考虑到安全应当使用Session。
4、Session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。考虑到减轻服务器性能方面,应当使用Cookie。
注意:为什么要用到会话机制?
HTTP协议是一种无状态协议,在数据交换完毕后,服务器端和客户端的链接就会关闭,每次交换数据都需要建立新的链接。此时,服务器无法从链接上跟踪会话。cookie可以跟踪会话,弥补HTTP无状态协议的不足。
六.Cookie的属性
Servlet Cookie常用的API:
(1)getName();获得名字;
(2)getValue();获得对应的值;
(3)setDomain(String domain);设置cookie的有效域名;
(4)setPath(String path);设置cookie的有效路径;
(5)setMaxAge(int maxAge);设置cookie的有效时间。
七.Cookie的使用
Cookie可以设置在客户端和服务端。这里练习用服务端Demo:
商品的浏览历史记录
步骤:
点击某个商品,将商品ID传递给一个Servlet
在Servlet中判断是否是第一次浏览商品
如果是第一次:将商品ID存入到cookie中
如果不是,判断商品是否被浏览过,如果浏览过,就 删除对应的cookie,添加到首尾,没有就判断是否达到浏览商品显示的最大值,
如果没有就直接添加到第一个,如果达到了就删除最后一个,再添加都首位
public class ServletDemo2 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收用户点击商品传递过来的id
String id = request.getParameter("id");
//获得所有的cookie信息
Cookie[] cookies = request.getCookies();
//判断有没有浏览过这个商品
Cookie cookie = CookieUtils.findCookie(cookies,id);
//用户是第一次浏览
if(cookie == null) {
//创建cookie对象
Cookie c = new Cookie("history", id);
//设置一个小时的销毁
cookie.setMaxAge(60*60);
//发送cookie
response.addCookie(c);
//用户不是第一次浏览
}else {
//得打cookie的值
String value = cookie.getValue();
//切掉在拼接cookie时的,号
String[] ids = value.split(",");
//将数组转换成集合
List<String> aslist = Arrays.asList(ids);
//将list转换成linkedlist
LinkedList<String> list = new LinkedList<>(aslist);
//如果用户之前浏览过这个商品
if(list.contains(id)) {
//删除对应的
list.remove(id);
list.addFirst(id);
//没有浏览过
}else {
//判断是否达到最大值
if(list.size() < 3) {
//直接添加到第一个
list.addFirst(id);
//达到最大值
}else {
//删除最后一个
list.removeLast();
list.addFirst(id);
}
}
//创建拼接的StringBuffer
StringBuffer sb = new StringBuffer();
for(String s:list) {
sb.append(s).append(",");
}
//去掉最后一个,号
String idValue = sb.toString().substring(0,sb.length()-1);
//保存到cookie中
Cookie c = new Cookie("history", idValue);
//发送
response.addCookie(c);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
class CookieUtils {
public static Cookie findCookie(Cookie[] cookies,String name){
if(cookies == null){
return null;
}else{
for(Cookie cookie:cookies){
if(name.equals(cookie.getName())){
return cookie;
}
}
return null;
}
}
}
清空浏览历史记录
点击清空浏览历史记录的超链接,
跳转到servlet
得到指定保存浏览历史记录的cookie,
设置保存时间为0
重定向到商品显示页面
public class Demo3Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获得所有的cookie
Cookie[] cookies = request.getCookies();
//遍历cookies,拿到保存浏览历史记录的cookie
for (Cookie cookie : cookies) {
if(cookie.getName().equals("history")) {
//设置保存时间为0
cookie.setMaxAge(0);
}
}
//重定向
response.sendRedirect(request.getContextPath()+"/list.jsp");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}