OkHttp 知识梳理(3) - OkHttp 之缓存基础
OkHttp 知识梳理系列文章
OkHttp 知识梳理(1) - OkHttp 源码解析之入门
OkHttp 知识梳理(2) - OkHttp 源码解析之异步请求 & 线程调度
OkHttp 知识梳理(3) - OkHttp 之缓存基础
一、缓存基础
在了解OkHttp
的缓存实现之前,我们先来复习一下HTTP
协议当中,与缓存有关的一些基础知识,这里,我们会介绍HTTP
中与缓存相关的首部字段,根据首部字段的作用,可以将其分为以下四类:
通用首部字段
- 请求报文和响应报文都会使用的首部。
Cache-Control
请求首部字段
- 从客户端向服务器发送请求报文时使用的首部,补充了请求的附加内容、客户端信息、响应内容相关优先级等信息。
-
If-Match
、If-Modified-Since
、If-None-Match
、If-Range
、If-Unmodified-Since
。
响应首部字段
- 从服务器向客户端返回响应报文时使用的首部,补充了响应的附加内容,也会要求客户端附加额外的内容信息。
ETag
实体首部字段
- 针对请求报文和响应报文的实体部分使用的首部,补充了资源内容更新时间等与实体有关的信息。
Last-Modified
二、通用首部字段
2.1 简介
在通用首部字段中,与缓存有关的字段为Cache-Control
。Cache-Control
是HTTP/1.1
的通用首部字段,通过指定它的值,就能够操作缓存的工作机制。指令的参数是可选的,多个指令之间通过","
分隔,首部字段Cache-Control
的指令可用于 请求及响应 时。
Cache-Control : private, max-age=0, no-cache
缓存请求指令
指令 | 说明 |
---|---|
no-cache |
强制向源服务器再次验证 |
no-store |
不缓存请求或响应的任何内容 |
max-age=[s] |
响应的最大age 值 |
max-stale=[s] |
接收已过期的响应 |
min-fresh=[s] |
期望在指定时间内的响应仍然有效 |
no-transform |
代理不可更改媒体类型 |
only-if-cached |
从缓存获取资源 |
cache-extension |
新指令标记 |
缓存响应指令
指令 | 说明 |
---|---|
public |
可向任意方提供响应的缓存 |
private |
仅向特定用户返回响应 |
no-cache |
缓存前必须先确认其有效性 |
no-store |
不缓存请求或响应的任何内容 |
no-transform |
代理不可更改媒体类型 |
must-revalidate |
可缓存但必须再向源服务器确认 |
proxy-revalidate |
要求中间缓存服务器对缓存的响应有效性再进行确认 |
max-age=[s] |
响应的最大age
|
s-maxage=[s] |
公共缓存服务器响应的最大age
|
cache-extension |
新指令标记 |
2.2 具体含义
2.2.1 public
Cache-Control : public
当指定使用public
指令时,则明确表示其它用户也可以利用缓存。
2.2.2 private
privateCache-Control : private
当指定private
指令时,响应只以特定的用户作为对象,这与public
指令的行为相反,缓存服务器会对该特定的用户提供资源缓存的服务,对于其他用户发送过来的请求,代理服务器则不会返回缓存。
2.2.3 no-cache
no-cacheCache-Control : no-cache
使用no-cache
的指令的目的是为了 防止从缓存中返回过期的资源。
客户端发送的请求 中如果包含no-cache
指令,则表示客户端将不会接收缓存过的指令。于是,“中间”缓存服务器必须把客户端请求转发给源服务器。
服务器返回的响应 中包含no-cache
指令,那么缓存服务器不能对资源进行缓存,源服务器以后也将不再对缓存服务器请求中提出的资源有效性进行确认,且禁止缓存服务器对响应资源进行缓存操作。
Cache-Control : no-cache=Location
由服务器返回的响应中,若报文首部字段Cache-Control
中对no-cache
字段名具体制定参数值,那么客户端在接收到这个被指定参数值的首部字段对应的响应报文后,就不能使用缓存,换言之,无参数值的首部字段可以使用缓存,只能在响应指令中指定该参数。
2.2.4 no-store
Cache-Control : no-store
当使用no-store
指令时,暗示请求(和对应的响应)或响应中包含机密信息,因此,该指令规定缓存不能在本地存储请求或响应的任一部分。
它和no-cache
的区别在于,no-cache
代表 不缓存过期的资源,而no-store
是 真正的不缓存。
2.2.5 s-maxage
Cache-Control : s-maxage=604800 (秒)
s-maxage
和max-age
指令的功能相同,它们的不同点是s-maxage
指令只适用于供多位用户使用的公共缓存服务器,也就是说,对于向同一用户重复返回响应的服务器来说,这个指令没有任何作用。
另外,当使用s-maxage
指令后,则直接忽略对Expires
首部字段及max-age
指令的处理。
2.2.6 max-age
max-ageCache-Control : max-age=604800 (秒)
当 客户端发送的请求 中包含max-age
指令时,如果判定缓存资源的缓存时间数值比指定时间的数值更小,那么客户端就接收缓存的资源。另外,当指定max-age
值为0
时,那么缓存服务器通常需要将请求转发给源服务器。
当 服务器返回的响应 中包含max-age
指令时,缓存服务器将不对资源的有效性再做确认,而max-age
数值代表资源保存为缓存的最长时间。
在HTTP/1.1
版本中,会优先处理max-age
指令,而忽略Expires
首部字段。
2.2.7 min-refresh
min-refreshCache-Control : min-refresh=60 (秒)
min-refresh
指令要求缓存服务器返回 至少还未过指定时间的缓存资源。比如,当指定min-refresh
为60s
后,在这60s
以内如果有超过有效期限的资源都无法作为响应返回了。
2.2.8 max-stale
Cache-Control : max-stale=3600 (秒)
使用max-stale
可指示缓存资源,即使过期也照常接收。如果指令未指定参数,那么无论多久,客户端都会接收响应;如果指令中指定了具体数值,那么即使过期,只要仍处于max-stale
指定的时间内,仍旧会被客户端接收。
2.2.9 only-if-cached
Cache-Control : only-if-cached
使用only-if-cached
指令表示客户端 仅在缓存服务器本地缓存目标资源的情况下才会要求其返回。换言之,该指令要求缓存服务器不重新加载响应,也不会再次确认资源有效性。若发生请求缓存服务器的本地缓存无响应,则返回504
。
2.2.10 must-revalidate
Cache-Control : must-revalidate
使用must-revalidate
指令,代理会 向源服务器再次验证即将返回的响应缓存目前是否仍然有效。
若代理无法连通源服务器再次获取有效资源的话,缓存必须给客户一条504
状态码。
另外,使用must-revalidate
指令会忽略请求的max-stale
指令。
2.2.11 proxy-revalidate
Cache-Control : proxy-revalidate
proxy-revalidate
指令要求所有的缓存服务器在接收到客户端带有该指令的请求返回响应之前,必须再次验证缓存的有效性。
2.2.12 no-transform
Cache-Control : no-transform
使用no-transform
指令规定无论是在请求还是响应中,缓存都不能改变主体的媒体类型。这样做可防止缓存或代理压缩图片等类似操作。
三、请求首部字段
在请求首部字段中,与缓存相关的字段为If-XXX
,像这种样式的请求首部字段,也称为条件请求,服务器接收到附带条件的请求后,只有判断指定条件为真时,才会执行请求。
3.1 If-Match
If-Match首部字段If-Match
会告诉服务器匹配资源所用的实体标记ETag
。服务器会比对ETag
的字段值与资源的ETag
值,仅当两者一致时,才会执行请求,反之则返回状态码412
。
还可以使用*
指定If-Match
的字段值,针对这种情况,服务器将会忽略ETag
的值,只要资源存在就处理请求。
3.2 If-Modified-Since
If-Modified-Since首部字段
If-Modified-Since
会告知服务器若字段值早于资源的更新时间,则希望处理该请求,反之,则返回状态码304
。
If-Modified-Since
用于确认代理或客户端拥有的本地资源的有效性,获取资源的更新日期时间,可通过确认首部字段Last-Modified
。
3.3 If-None-Match
If-None-Match和
If-Match
作用相反。
3.4 If-Unmodified-Since
和If-Modified-Since
作用相反。
四、响应首部字段
首部字段ETag
能告知客户端实体标识。它是一种可将资源以字符串形式做唯一性标识的方式。服务器会为每份资源分配对应的ETag
值。
另外,当资源更新时,ETag
值也需要更新。生成ETag
值时,并没有统一的算法规则,而仅仅是由服务器来分配。
强 ETag 值和弱 ETag 值
- 强
ETag
值,无论实体发生多么细微的变化都会改变其值。 - 弱
ETag
值,只用于提示资源是否相同。只有资源发生了根本改变,产生差异时才会改变ETag
的值。
五、实体首部字段
首部字段Last-Modified
指明资源最终修改的时间。一般来说,这个值就是Request-URI
指定资源被修改的时间。但类似使用CGI
脚本进行动态数据处理时,该值有可能会变成数据最终最终修改时的时间。