Cookie和Web缓存机制

来源:互联网 发布:先导爱知在g出现吗 编辑:程序博客网 时间:2024/06/11 14:49

本周阅读了JS高程的缓存机制部分,对于Cookie和Web缓存机制有了更深的了解,今年二三月份参加实习生电面多次被问到Cookie以及LocalStorage、SessionStorage的区别,当时对于每一部分都有个大致的了解,且没有实际运用,所以趁这次机会,也动手实现了一把,写下这篇博客以整理思路。

缓存机制对于用户访问网页来说是很方便的。如果将用户名,偏好设定或者其他一些数据存储到客户端,而不必每次访问网页都输入数据,可能对于用户体验会更好。常用的缓存机制有Cookie和Web缓存机制这两大类。

Cookie机制

Cookie应该算是HTTP里面的一个概念。关于HTTP协议,我会在HTTP模块整理一篇博客详细介绍,这里先做简单说明:在客户端请求服务端数据的时候,会发送一个HTTP请求,这个HTTP请求有头部信息,还有HTTP数据报文等等,服务端在接收到客户端的HTTP请求之后,会进行一些操作,然后发送一个HTTP响应给客户端,这个响应也包含头部信息和数据报文。响应头部里面会包含HTTP状态码,表示响应是否成功。如果不成功,其原因是什麽。
而加入Cookie的过程又是怎么样的?看下图:
这里写图片描述
- 首先,当客户端第一次访问服务器时,先发送HTTP请求给服务端;
- 服务端在收到客户端发来的HTTP请求之后,会在本服务器上做一些操作,操作结束会根据结果发一个HTTP响应给客户端。这时候,会在HTTP响应报文的头部中加入:Set-Cookie: name = value,并把该信息存储到本服务器上(Session);
- 客户端收到HTTP响应报文之后,会检查Set-Cookie字段,并将其值存储到浏览器中。当客户端第二次再去访问该服务器时,会将之前保存的信息取出来并在HTTP请求头部加上一个Cookie:name = value
- 这时候服务器收到HTTP请求报文之后,将Cookie取出来,与服务器存储的Session进行匹配,如果匹配上,用户信息验证成功。

Cookie限制

Cookie是保存在客户端磁盘上的,所以不宜占据太多磁盘空间。同时,Cookie是绑定在特定域名上的。当设定了一个Cookie之后,再给创建它的域名发一个请求时,还会包含该Cookie。所以对Cookie的限制是对每个域来说的。但各个浏览器也有不同:
IE6及以下每个域名最多包含20个Cookie;
IE7及以上每个域名最多50个Cookie;
Firefox每个域名最多50个Cookie;
Opera下每个域名最多30个Cookie;
Sarafi和Chrome对每个域的Cookie数目没有严格限制。

每个Cookie最大是4096B(加减一)。即对于大多数浏览器来说,Cookie大小是4096个字节,而对于少数浏览器,有的是4097B,而有的是4095B.因此为了浏览器兼容性,最好将Cookie大小限制在4095B之内。

Cookie是什么形式的

Cookie有名称,值,过期时间,域,路径,安全标志这几个部分。
比如:
Set-Cookie: name=”Liu”;expires:Mon, 29-05-2017 00:00:00 GTM;domain=”baidu.com”;path=/;secure
上面这个形式设置了一个名称为name的Cookie,它的值为”Liu”,到2017年5月29的凌晨过期,对于baidu.com和www.baidu.com及其子域都有效,并且该cookie是安全的,这意味着只能通过SSL连接(如https)来发送,而仅仅用http协议是不能发送的。

Cookie与JavaScript

Cookie也可以利用JavaScript来操作。只不过涉及到一些字符串解析等一些比较繁琐的过程。我们可以通过document.cookie来读取或者设置Cookie。

document.cookie = "age=20";

这里写图片描述

打开浏览器进行调试,可以看到在Application中的Cookies选项中,有了名称为age,值为20的cookie.
需要注意的一点是:直接在本机利用JS去设置cookie是没有用的,因为你要设置cookie 服务器必须发一个set-cookie,所以需要启一个服务器。

上面是设置简单cookie的方式,下面介绍设置和获取cookie复杂的方式,或者说通用方法。
我们可以把设置Cookie和获取Cookie封装到一个对象中,然后通过对象去调它的方法。并且要知道cookie的结果,类似于下面这样:
name=”Liu”;expires=”05-05-2017 00:00:00 GTM;path=/;secure”

var UtilC = {    get : function(cname){        var cookieName = cname + "=";        var CStart = document.cookie.indexOf(cookieName);        //找到要获取的cookie名在document.cookie中的位置        if(CStart != -1)        {            var CEnd = document.cookie.indexOf(";", CStart);//判断该cookie是否被设置了多个选项            if(CEnd == -1)             {            //若从该cookie选项之后只有一个选项,直接返回'='后到末尾的字符串                return document.cookie.substring( CStart + cookieName.length);            }            else            {            //若该选项之后设置了多个选项,则返回'='之后';'之前的字符串                return document.cookie.substring( CStart + cookieName.length, CEnd);            }        }        else            return false;  //若在document.cookie中没有找到要获取的cookie名,返回false    },    set : function(name, value, expires, path, domain, secure){    //设置cookie时对于中文的字符必须要编码            var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value);            if(expires instanceof Date)            {                cookieText += ";expires=" + expires.toGMTString();            }            if(path)            {                cookieText += ";path=" + path;            }            if(domain)            {                cookieText += ";domain=" + domain;            }            if(secure)            {                cookieText += ";secure";            }        document.cookie = cookieText;    },    removeCookie: function(name){    //删除cookie时将其过期时间设为过去的一个时间就可以了        this.set(name, '', new Date(0));    }}UtilC.set('name', 'Hellen'); console.log(UtilC.get("name"));    //输出Hellen 

当调用下面代码之后

UtilC.set('name', 'Hellen');

浏览器调试窗口中的Application如下图所示:
这里写图片描述
可以看到名为name,值为Hellen的cookie被清除了。

子Cookie

由于cookie的个数以及大小限制,出现了子cookie,它相当于cookie的一小段,格式可能类似下面这样:
name=name1=”Liu”&name2=”Yang”&name3=”Chen”
这就是一个名为name的cookie,但是它又有3个子cookie。
同样也可以利用JS写一个设置cookie或获取cookie的通用方法,但是主要这时设置可以设置某个cookie选项,也可以设置某个cookie 选项中某一个子cookie的值。看代码:

var UtilCookie = {    get : function(Cname, name){        var data = this.getAllCookie(Cname);        if(data[name])            return data[name];        else            return false;   },   getAllCookie : function(cookieName){       cookieName = cookieName + "=";       var res = {};       var CStart = document.cookie.indexOf(cookieName);       if(CStart != -1)       {           var CEnd = document.cookie.indexOf(";", CStart);           if(CEnd == -1)           {                CStartStr = document.cookie.substring( CStart + cookieName.length);                var part = CStartStr.split("&");                for(var i = 0; i < part.length; i++)                {                    var partP = part[i].split("=");                    res[partP[0]] = partP[1];                }            }            else            {                CStartStr = document.cookie.substring( CStart + cookieName.length, CEnd);                var part = CStartStr.split("&");                for(var i = 0; i < part.length; i++)                {                    var partP = part[i].split("=");                    res[partP[0]] = partP[1];                }            }            return res;        }        else        {            return false;        }    },    setAll: function(Cname, subcookie, expires, path, domain, secure){        var CText = encodeURIComponent(Cname) + "=";        var Arr = [];        for(subName in subcookie)        {            if(subName.length > 0 && subcookie.hasOwnProperty(subName))            {                Arr.push(encodeURIComponent(subName) + "=" + encodeURIComponent(subcookie[subName]));            }        }        if(Arr.length > 0)        {            CText += Arr.join("&");        }        if(expires instanceof Date)        {            CText += ";expires=" + expires.toGMTString();        }        if(path)        {            CText += ";path=" + path;        }        if(domain)        {            CText += ";domain=" + domain;        }        if(secure)        {            CText += ";secure";        }        document.cookie = CText;    },    set : function(name, subName, value, expires, domain, path, secure){        var subcookie = this.getAllCookie(name);        subcookie[subName] = value;        this.setAll(name, subcookie, expires, path, domain, secure);    }}//子cookie的格式: name=name1="Liu"&name2="Hellen"&name3="Yang";UtilCookie.setAll( "name", { name1:"Liu", name2:"Yang", family:"YL" });UtilCookie.get("name", "name1");

此时,浏览器的Application中就可以看到设置的cookie了。
这里写图片描述

Web缓存机制

Web 缓存的出现主要是为了弥补cookie带来的一些局限,当数据严格控制在客户端时,可以不用通过HTTP来持续得将数据发给服务器。

主要使用比较多的就是sessionStorage和localStorage,这两种都是Storage类型,Web Storage提供一个Storage类型,它有下面这么写方法:
getItem(item);
setItem(item, value)
removeItem(item)
所以sessionStorage和localStorage都可以调用上面的方法。

SessionStorage

sessionStorage.setItem("Age", 20);

浏览器中就可以看到Session Storage中有Age这个缓存
这里写图片描述
当关闭该页面,重新访问时(没有了设置sessionStorage),此时在Application里的SessionStorage并没找到Age这个缓存,说明Session Storage是基于会话的,也就是说当前页面关闭之后,session Storage就消失了。
localStorage

localStorage.setItem("Age", 20);

这里写图片描述
当浏览器关闭,重新打开时,看到localStorage中还有Age这个缓存,因此localStorage是永久缓存的,除非手动清除,否则它会一直存在,上图中的musics,searchHistory等等正说明了这一点。
清除localStorage可以调Storage类型的接口:

localStorage.removeItem("Age");

以上是我这次关于缓存机制的总结和分享,希望大家可以共同讨论和进步!

原创粉丝点击