2: 浏览器缓存中涉及到的头信息
浏览器的缓存是依靠请求和响应中的的头信息来控制缓存的。html
1: expires
最简单的过时缓存方式, 在第一次请求时返回的头信息中设置一个exires时间,在后面的请求的时候, 请求会带着这个expires时间, 假如在这个expires时间内,浏览器不会向服务器发送请求, 而是直接从本地缓存副本中读取数据数据库
2:Cache-Control
他有一些不一样的值对应不一样的缓存策略,这里我查到一个,参考一下初探 HTTP 1.1 Cache 機制
这里要说明的是Cache-Control的设置会覆盖expires的设置, 并且常与Last-Modified和Etag配合使用segmentfault
3:Last-Modified/Last-Modified-Since
在使用这个缓存策略的时候, 浏览器每次都会向服务器发送请求, 但服务器能够根据Last-Modified-Since向浏览器返回200或者304, 若是返回304, 就是告诉浏览器让它直接从客户端电脑的缓存中读取副本吧, 不然就会把请求的资源以200的方式返回给浏览器。浏览器
这里也要说明一下, Last-Modified是浏览器第一次向服务器请求以后, 服务器响应中设置的(即代码中设定), 而Last-Modified-Since则是浏览器每次向服务器请求的时候带着的Last-Modified的值, 好比第一次请求后响应的Last-Modified的值是A, 那么在后面每次请求的时候的Last-Modified-Since的值就是A, 直到服务器从新设置了Last-Modified的值缓存
4: Etag/If-None-Match
ETag是一种与Last-Modified/Last-Modified-Since相似的控制方式。用户在第一次请求的时候服务器能够本身生成或由用户生成, 而后响应给浏览器, 那么在之后的请求中,会带着If-None-Match, 它的值就是以前生成的Etag。 在服务器中对比服务器上的Etag与If-None-Match, 假如相同, 则返回304, 不然请求并返回服务器资源。服务器
这里有一个问题, 如何生成Etag, 尤为是动态页面中, 假如资源发生变化, Etag要从新生成。 我这里想到一种方式, 请求到服务器后, 仍是要进行必要的代码运行, 在代码中, 拿到相关的变量生成一个Etag值, 对比传递上来的If-None-Match, 再断定返回的状态值。(原谅个人经验有限, 这只是一种方式,若是各位有新的思路, 欢迎加入讨论)。函数
5: Cache-Control/Expires的优先级要高于Last-Modified/Etag,Cache-Control/Expires是控制浏览器是否向服务器拉资源, Last-Modified/Etag是服务器控制是否返回一个完整的请求资源,仍是返回一个304, 假如本地连请求都不会拉, 那Last-Modified/Etag就无从谈起了.post
下面使用PHP分别实现以上几种缓存方式, 通常服务器上的静态文件都会默认使用Last-Modified/Last-Modified-Since, 因此不少的静态文件在二,三,四。。。次刷新的时候都是304状态(Not Modified). 另外下面的过时时间都是格林威治时间才行,可使用gmdate函数获取。
/* Last-Modified/Last-Modified-Since 我想这里若是用一些数据保存方式,如memcache或数据库, 把某个文件的修改时间保存起来, 若是文件修改了, 则更新这个数据, 而后每次刷新这里的这个页面的时候,先读取修改时间, 若是传递的$lastModifiedSince修改时间不符, 则从新读取, 不然返回304 测试的结果是在在缓存时间内返回304 */ $cacheTime = 60; $lastModifiedSince = strtotime(@$_SERVER['HTTP_IF_MODIFIED_SINCE']); if($lastModifiedSince + $cacheTime > time()) { header("HTTP/1.1 304"); die('use cache'); } header('Last-Modified: '.gmdate('D d M Y H:i:s', time()).' GMT'); echo time(); /* Etag/If-None-Match 测试的结果是在服务器上的资源未发生变化时返回的304 */ $user_id = 1; $etag = md5($user_id); $matchEtag = @$_SERVER['HTTP_IF_NONE_MATCH']; if($matchEtag == $etag) { header("HTTP/1.1 304"); die('use cache'); } header('Etag: '.$etag); echo time();
在测试expires和Cache-Control的max-age的时候, 本地缓存无效, 每次仍是发起请求, 并无读取缓存, 不知为什么?
请看链接测试
PS: 文章中可能有错误的地方, 若是发现, 请及时指出code