2010-07-30 35 views
10

有沒有人知道如何去編碼一個servlet過濾器,它將在給定的文件/內容類型的響應上設置緩存頭?我有一個提供大量圖像的應用程序,並且我希望通過讓瀏覽器緩存不經常更改的緩存來減少託管帶寬。理想情況下,我希望能夠指定內容類型,並在內容類型匹配時設置適當的標題。用於瀏覽器緩存的Servlet過濾器?

有沒有人知道如何去做這件事?或者,甚至更好,有他們願意分享的示例代碼?謝謝!

回答

15

在你的過濾器這一行:

chain.doFilter(httpRequest, new AddExpiresHeaderResponse(httpResponse)); 

凡響應包裝的樣子:

class AddExpiresHeaderResponse extends HttpServletResponseWrapper { 

    public static final String[] CACHEABLE_CONTENT_TYPES = new String[] { 
     "text/css", "text/javascript", "image/png", "image/jpeg", 
     "image/gif", "image/jpg" }; 

    static { 
     Arrays.sort(CACHEABLE_CONTENT_TYPES); 
    } 

    public AddExpiresHeaderResponse(HttpServletResponse response) { 
     super(response); 
    } 

    @Override 
    public void setContentType(String contentType) { 
     if (contentType != null && Arrays.binarySearch(CACHEABLE_CONTENT_TYPES, contentType) > -1) { 
      Calendar inTwoMonths = GeneralUtils.createCalendar(); 
      inTwoMonths.add(Calendar.MONTH, 2); 

      super.setDateHeader("Expires", inTwoMonths.getTimeInMillis()); 
     } else { 
      super.setHeader("Expires", "-1"); 
      super.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); 
     } 
     super.setContentType(contentType); 
    } 
} 

總之,這將創建一個響應包裝,其上設置內容類型,增加了expires標題。 (如果你願意,你可以添加任何你需要的其他標題)。我一直在使用這個過濾器+包裝,它的工作原理。

See this question對這個問題的解決,以及BalusC的原始解決方案。

+3

或者,如果您將所有這些文件都放在一個公共文件夾中, '/ static',然後將過濾器映射到'/ static/*'的'url-pattern'上,這樣你就不需要每次都檢查內容類型,並且可以直接設置響應頭。 – BalusC 2010-07-30 20:20:10

+0

由於容器會自動添加Pragma和Cache-Control標頭,因此這不適用於GlassFish上的SSL/TLS資源。如果你想緩存這些資源,你需要刪除/覆蓋這些頭像:super.setHeader(「Pragma」,null);和super.setHeader(「Cache-Control」,null)。 Cache-Control:「public」也可能起作用。注意:使用null可能不便攜,因爲它不在規範中。可能有一種方法可以禁止添加標題的容器,但它沒有很好的記錄。 – Ryan 2014-10-16 18:27:13