3. CacheControl 指令详解:max‑age、no‑cache、no‑store、must‑revalidate 等常用值

3.1 原理:Cache‑Control 在 HTTP 缓存中的角色

HTTP 的 Cache‑Control 头部是服务端与客户端协商缓存策略的核心协议。OkHttp 的缓存模块完全遵循 RFC 7234,通过解析该头部中的指令来决定是否缓存、缓存多久以及何时必须重新验证。每个指令都是一个键值对或标记,组合后形成完整的缓存策略。

在同步请求场景中,Cache‑Control 直接影响 OkHttp 的 CacheInterceptor 行为:

  • 请求指令(由客户端发送)—— 告知服务端或中间缓存客户端的偏好,例如只接受新鲜度低于 30 秒的资源。
  • 响应指令(由服务端返回)—— 指示缓存层如何存储和复用该响应。

本章聚焦响应指令中四个最常用的值,并延伸介绍 public、private、s‑maxage 等辅助指令。

3.2 核心指令速查表

指令 方向 语义 典型值示例 对 OkHttp 缓存的影响
max‑age 响应 / 请求 资源在缓存中的最大有效秒数 max‑age=3600 缓存过期前可直接复用;过期后需重新验证或丢弃
no‑cache 响应 缓存必须向源服务器验证资源是否仍有效 no‑cache 每次使用前都会发起条件请求(If‑Modified‑Since / ETag)
no‑store 响应 禁止任何中间缓存或私有缓存存储该响应 no‑store OkHttp 不会将响应写入磁盘缓存,直接透传
must‑revalidate 响应 缓存过期后必须向源服务器验证,不得使用过期缓存 must‑revalidate 即使设置了 max‑age,过期后也必须回源验证
public 响应 任何缓存(包括 CDN)都可以缓存 public 与 max‑age 配合,允许共享缓存存储
private 响应 仅私有缓存(如 App 本地缓存)可以缓存 private OkHttp 视为可缓存,但中间代理不得缓存
s‑maxage 响应 针对共享缓存的专用 max‑age s‑maxage=600 优先级高于 max‑age,但 OkHttp 作为私有缓存会忽略
教学提示: 在 OkHttp 中,no‑cache ≠ no‑store。no‑cache 允许缓存存储响应,但每次使用时必须验证;no‑store 则完全禁止存储。两者常被混淆,但语义差异巨大。

3.3 指令决策流程

当 OkHttp 的 CacheInterceptor 收到服务端响应时,会按照下图顺序检查 Cache‑Control 指令,最终决定是否缓存以及如何设置过期策略。

Cache‑Control 响应指令决策流程 HTTP 响应到达 解析 Cache-Control no‑store ? 禁止缓存 no‑cache ? 每次需验证 max‑age ? 计算过期时间 must‑revalidate ? 过期必须验证 缓存响应并设置策略 是 否