http头字段缓存详解(2)(总结和实例)
Cache-Control
请求头Cache-Control:max-age=0,(F5刷新会出现的效果) 表示虽然过期但是会通过向服务器验证是否缓存可用。
请求头里Cache-Control=no-cache
表示浏览器不想读缓存,并不是说没有缓存。(ctrl+F5强制刷新时,直接请求服务器的效果)
响应头中 Cache-Control=no-cache (目的:强制确认缓存)
表示浏览器使用缓存的资源之前,必须通过请求头If-None-match和响应头ETag来验证有效性(返回304未修改状态码)。
(ps:同样的no-cache值,在响应和请求头中的意思是不同的)
其他值:
Public :表示该响应可以再浏览器或者任何中继的Web代理中缓存,public是默认值 Private :表示只有用户的浏览器可以缓存 no-store :表示内容都不会被缓存 must-revalidation/proxy-revalidation :如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证
PS : no-cache和must-revalidate区别: no-cache表示使用缓存必须验证 must-revalidate表示使用过期的缓存必须验证
max-age=xxx :缓存的内容将在xxx秒后失效(只在HTTP1.1中可用)和Last-Modified一起使用时优先级较高
Pragma
它的行为和 Cache-Control: no-cache 一致 区别: Pragma 是HTTP/1.0,仅用于兼容 HTTP/1.0 客户端。 Cache-Control 是HTTP/1.1
如果使用Pragma将忽略Expires和Cache-Control头。
Expires
Expires和Cache-Control区别: Expires :某个时间点前(HTTP1.0版本)。 Cache-Control: max-age=持续多长时间(HTTP1.1版本)
缓存清理过程:
当客户端发起一个请求时,缓存检索到已有一个对应的缓存副本,则缓存会先将此请求附加一个If-None-Match头,然后发给目标服务器, 若服务器返回了 304 (Not Modified)(该响应不会有带有实体信息) (通过If-None-Match 或 If-Modified-Since判断后发现已过期,那么会带有该资源的实体内容返回,将覆盖原来的缓存)
Cache-control:max-age 和 Expires 和 Last-Modified的优先级
1,如果设置了 "Cache-control: max-age=N" 头部,那么新鲜度的生命期则等于 N。未设置此头部,则会检查 Expires 头部是否存在, 2,若 Expires 头部存在,则新鲜度生命期 等于 该头部的值 减去 Date 头部的值。 3,若两种头部都未设置,则会查找 Last-Modified 头部,新鲜度生命期 等于 Date 头部值 减去 Last-modified 头部值 再除以 10。
资源版本化
需求:
很多页面都引用了一些JS和CSS文件,当这些文件的内容变动时,我们希望能尽快地让其在缓存中更新。
其原理是:
将那些经常更新的文件的文件名通过一种特别的方式来命名,
即文件名中加入版本号,这样一来,每一次文件内容改变,文件名也被一起改变,就相当于新建了另一个不同的资源,
那我们就可以将该资源设置为永久不过期了(通常设置为1年以上)。
强验证器(ETag/If-None-Match) 或 弱验证器(Last-Modified/If-Modified-Since)
响应报文中的 ETag 头被用来作为强验证器, 若在服务器的响应报文中含有 ETag 头部, 则后续客户端发起同一请求时,会附加一个 If-None-Match 头部(其值为之前Etag的值)用于让服务器验证该请求对应的缓存是否新鲜。 响应报文中的 Last-Modified 头用来作为弱验证器, 之所以作为“弱”,是因为它最多只能精确到秒, 若服务器的响应报文中存在 Last-Modified 头部,那么客户端发起一个 If-Modified-Since 请求来验证缓存是否新鲜。 当发起了一个验证请求, 服务器可以忽略此验证请求并返回一个正常的 200 OK 响应报文, 或者也可以返回 304 Not Modified(带有一个空的实体)来告知浏览器:
可变响应 - Vary头部
响应报文中的 Vary 头部用于 决定如何匹配后续请求的头部,从而决定是否采用某缓存副本,而不是从服务器获得一个新的副本。
当发起一个请求时,那么缓存需要检查 Vary 头部中所列出的头部字段,
若在当前请求中的这些头部字段值 与 缓存副本中响应的头部字段值匹配,
那么可以使用此缓存副本,否则需要不能使用此副本(重新请求服务器)。
当我们使用 Vary: User-Agent 头部时,缓存服务器就需要去查看新发起的请求的 User-Agent 头部是否匹配,然后再决定是否采用缓存。 如果你需要为手机端用户展示不同的内容,此举可以防止将电脑端的缓存错误地提供给了手机端的用户 Vary: User-Agent 由于 User-Agent 头部在移动端和电脑端中的值都是不同的,所以缓存就不会错误地将移动端内容提供给电脑端用户


JSP禁用缓存的方式
使用服务器端控制AJAX页面缓存: response.setHeader( "Pragma", "no-cache" ); response.addHeader( "Cache-Control", "must-revalidate" ); response.addHeader( "Cache-Control", "no-cache" ); response.addHeader( "Cache-Control", "no-store" ); response.setDateHeader("Expires", 0); 单纯的使用 xmlhttp.setRequestHeader("Cache-Control","no-cache")无效。
条件请求
当客户端缓存了目标资源但不确定该缓存资源是否是最新版本的时候,就会发送一个条件请求. 在进行条件请求时,
1,客户端会提供给服务器一个If-Modified-Since请求头,其值为服务器上次返回的Last-Modified响应头中的日期值, 2,还会提供一个If-None-Match请求头,值为服务器上次返回的ETag响应头的值
服务器会读取到这两个请求头中的值,判断出客户端缓存的资源是否是最新的, 如果是的话,服务器就会返回HTTP/304 Not Modified响应,但没有响应体.客户端收到304响应后,就会从缓存中读取对应的资源. 另一种情况是,如果服务器认为客户端缓存的资源已经过期了,那么服务器就会返回HTTP/200 OK响应,响应体就是该资源当前最新的内容.
客户端收到200响应后,就会用新的响应体覆盖掉旧的缓存资源.
只有在客户端缓存了对应资源且该资源的响应头中包含了Last-Modified或ETag的情况下,才可能发送条件请求.
为什么要使用条件请求
当用户访问一个网页时,条件请求可以加速网页的打开时间(因为可以省去传输整个响应体的时间),
但仍然会有网络延迟,因为浏览器还是得为每个资源生成一条条件请求,并且等到服务器返回HTTP/304响应,才能读取缓存来显示网页.
更理想的情况是,服务器在响应上指定Cache-Control或Expires指令,这样客户端就能知道该资源的可用时间为多长,
也就能跳过条件请求的步骤,直接使用缓存中的资源了.
可是,即使服务器提供了这些信息,在下列情况下仍然需要使用条件请求: 在超过服务器指定的过期时间之后 如果用户执行了刷新操作的话

浙公网安备 33010602011771号