1. 程式人生 > >關於資訊頭Cache-Control的那些事兒

關於資訊頭Cache-Control的那些事兒

首先先簡單科普一下相關內容(其實我就是做個筆記w-。-)

       HTTP協議中常用的快取資訊頭關鍵字大概有四個:Cache-Control(HTTP1.1),Pragma(HTTP1.0),Expires和last-Modified。

              Cache-Control和Pragma都是可以控制頁面快取與否的,只是支援的協議版本不同而已,通常這兩個資訊頭都是同時存在的。而為了保險,一般也會加上Expires。

              Expires則是網頁快取的失效日期,這個必須設定GMT格式時間。也可以設定成0,此時失效日期預設為Wed, 31 Dec 1969 23:59:59 GMT,頁面快取肯定是過期的。

              last-Modified是頁面最後的更新時間,同樣需要時GMT格式時間。如果更新這個時間,Client端可以選擇是使用快取還是重新從伺服器更新站點資訊。

       值的一提的是在JSP中設定Expires和last-Modified時要使用long值(也許和dtd有關),也就是那個1970年1月1日 00:00:00以來到期望時間點的毫秒數。

       目前IE常用的HTTP協議通常都屬於HTTP1.1,這裡就說說這個Cache-Control。(非IE的瀏覽器大多都有自己的快取機制,就不多說了。)

              Cache-Control在處理快取的時候常用的值有如下四個:

              ①no-cache,瀏覽器和快取伺服器都不應該快取頁面資訊;

              ②public,瀏覽器和快取伺服器都可以快取頁面資訊;

              ③no-store,請求和響應的資訊都不被儲存;

              ④must-revalidate,客戶端每次發出請求都要驗證快取是否已經過期;

然後說說最近遇到的一個問題,最近發現IE11的一些較新的版本的補丁包更新之後,讀取快取中的非迴圈gif時,gif不能動了,只有首次請求該gif資源的時候才能動一次。

       於是我在web.xml裡添加了一個過濾類XxxFilter,重寫了servlet-api.jar裡面的Filter介面中的doFilter方法,在裡面給ServletResponse的物件設定了header屬性。

              大概就是這麼設定的:response.setHeader("Cache-Control", "no-cache");response.setHeader("pragma", "no-cache");

       然後考慮到不可能把頁面所有的資源都不做快取,這樣每次請求都要下載資源,實在有點不爽,就又增加了一層判斷。

              大概是這麼判斷的:

              if(request.getServletPath().endsWith(".gif") || request.getServletPath().endsWith(".GIF")){

                     response.setHeader("Cache-Control", "no-cache");

                     response.setHeader("pragma", "no-cache");

              }

       這樣判斷當次請求的相對路徑是不是一個gif圖片的請求,這樣就可以只把gif的快取遮蔽掉了,瞬間覺得舒服多了。

       一切搞定之後在我的64位Win7開啟IE8試了一下,非常完美,只有gif檔案沒有快取下來。

       IE9試了下沒問題,IE10有一點小問題,快取沒有能夠遮蔽掉,gif檔案仍然被快取了下來,但是gif檔案每次都是會動的可以原諒它了。

       IE11試了下,完蛋,不僅快取沒有遮蔽掉,gif讀取快取的時候就不會動了,我又試了一下比較老的IE11補丁包,和IE10的狀況是一樣的,不過gif讀快取是可以動的。

       經過一番查詢發現,原來從IE10開始已經無法解析no-cache了,只能換用no-store了,於是把no-cache換成了no-store,同時pragma的也換掉,之前測試過的全版本IE都沒有問題了。

              if(request.getServletPath().endsWith(".gif") || request.getServletPath().endsWith(".GIF")){

                     response.setHeader("Cache-Control", "no-store");

                     response.setHeader("pragma", "no-store");

              }

最後說下另一種處理gif再次播放不會動的辦法,就是請求gif的時候給gif檔案加一個時間字尾,這樣每次請求都是新的gif地址,不過這樣會有大量冗餘快取,不是太好。

OK收工。