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