一、快取基礎
在瞭解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
Cache-Control : private
複製程式碼
當指定private
指令時,響應只以特定的使用者作為物件,這與public
指令的行為相反,快取伺服器會對該特定的使用者提供資源快取的服務,對於其他使用者傳送過來的請求,代理伺服器則不會返回快取。
2.2.3 no-cache
Cache-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
Cache-Control : max-age=604800 (秒)
複製程式碼
當 客戶端傳送的請求 中包含max-age
指令時,如果判定快取資源的快取時間數值比指定時間的數值更小,那麼客戶端就接收快取的資源。另外,當指定max-age
值為0
時,那麼快取伺服器通常需要將請求轉發給源伺服器。
當 伺服器返回的響應 中包含max-age
指令時,快取伺服器將不對資源的有效性再做確認,而max-age
數值代表資源儲存為快取的最長時間。
在HTTP/1.1
版本中,會優先處理max-age
指令,而忽略Expires
首部欄位。
2.2.7 min-refresh
Cache-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
會告訴伺服器匹配資源所用的實體標記ETag
。伺服器會比對ETag
的欄位值與資源的ETag
值,僅當兩者一致時,才會執行請求,反之則返回狀態碼412
。
還可以使用*
指定If-Match
的欄位值,針對這種情況,伺服器將會忽略ETag
的值,只要資源存在就處理請求。
3.2 If-Modified-Since
首部欄位If-Modified-Since
會告知伺服器若欄位值早於資源的更新時間,則希望處理該請求,反之,則返回狀態碼304
。
If-Modified-Since
用於確認代理或客戶端擁有的本地資源的有效性,獲取資源的更新日期時間,可通過確認首部欄位Last-Modified
。
3.3 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
指令碼進行動態資料處理時,該值有可能會變成資料最終最終修改時的時間。