HTTP If-Modified-Since引起的瀏覽器緩存彙總

在看Spring中HttpServlet的Service方法時,對於GET請求,代碼邏輯以下:html

if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        }

其中涉及的關鍵信息是修改時間,這就涉及到瀏覽器數據緩存問題。如下對個緩存機制進行簡單總結,可用於請求的優化。(本文中的圖都摘自其餘文章前端

Last-Modified和If-Modified-Since

當瀏覽器GET請求的時候,若是有If-Modified-Since,則會與當前服務器上相關資源最後一次修改時間進行對比,若是相同則返回304(資源可訪問,但沒修改),不然加載最新數據,瀏覽器再緩存起來。這樣減小網絡數據傳輸和服務器壓力。gulp

ETags和If-None-Match

根據修改時間判斷文件是否被修改,若是一個網頁被頻繁更新,但實際內容並無更新,依然會對服務器形成壓力。引入了ETags和If-None-Match,其不一樣於Last-Modified和If-Modified-Since取決於修改時間,能夠依賴其餘屬性,如資源的MD5等。當資源被更新,但實際內容沒有更新,則會比較修改時間和ETags,若是ETags沒變,則不更新數據資源。但查閱源碼戴發現,目前底層實現上實現的是弱Etags,其由文本長度和修改時間組成,資源被更新後,ETags依然會更新。在AbstractResource中,代碼以下:瀏覽器

  @Override
    public final String getETag() {
        if (weakETag == null) {
            synchronized (this) {
                if (weakETag == null) {
                    long contentLength = getContentLength();
                    long lastModified = getLastModified();
                    if ((contentLength >= 0) || (lastModified >= 0)) {
                        weakETag = "W/\"" + contentLength + "-" +
                                   lastModified + "\"";
                    }
                }
            }
        }
        return weakETag;
    }

 

Expires

添加Expires頭能有效的利用瀏覽器的緩存能力來改善頁面的性能,能在後續的頁面中有效避免不少沒必要要的Http請求,WEB服務器使用Expires頭來告訴Web客戶端它可使用一個組件的當前副本,直到指定的時間爲止。例如:Expires:Thu,15 Apr  2010  20:00:00  GMT;  他告訴瀏覽器緩存有效性持續到2010年4月15日爲止,在這個時間以內相同的請求使用緩存,這個時間以外使用http請求。Expires有一個很是大的缺陷,它使用一個固定的時間,要求服務器與客戶端的時鐘保持嚴格的同步,而且這一天到來後,服務器還得從新設定新的時間。緩存

Cache-Control

HTTP1.1引入了Cathe-Control,它使用max-age指定組件被緩存多久(時間相對請求的時間),從請求開始在max-age時間內瀏覽器使用緩存,以外的使用請求,這樣就能夠消除Expires的限制。但有個缺點就是,用戶不能第一時間拿到最新修改的文件。請求過程以下:性能優化

 

另外,gulp 給靜態資源文件添加hash(md5)後綴防止緩存無效,能獲取最新文件(這個須要進一步研究)服務器

參考:網絡

HTTP的請求頭標籤 If-Modified-Since less

If-Modified-Since和If-None-Match前端性能

http://www.360doc.com/content/17/0721/17/41344223_673116604.shtml 

前端性能優化 —— 添加Expires頭

相關文章
相關標籤/搜索