2013-07-23 24 views
3

我試圖使用Spring MVC控制器來服務某些資產。我的資產是數據庫管理的,因此必須以這種方式提供服務。該服務從數據庫中查找資產的元數據,從文件系統讀取文件並構建響應。無法緩存由Spring MVC提供的圖像

這是我的控制器的樣子。

@Controller 
@RequestMapping("/assets") 
public class AssetController { 

    @Autowired 
    private AssetService assetService; 

    @RequestMapping("/{assetName:.+}") 
    public ResponseEntity<byte[]> getAsset(@PathVariable("assetName") String assetName) throws FileNotFoundException, IOException { 
     Asset asset = assetService.findByName(assetName); 

     HttpHeaders headers = new HttpHeaders(); 
     headers.setContentType(MediaType.valueOf(asset.getContentType())); 
     headers.setCacheControl("max-age=1209600"); 
     headers.setLastModified(asset.getModifiedOn().getTime()); // always in the past 

     return new ResponseEntity<byte[]>(assetService.toBytes(asset), headers, OK); 
    } 
} 

看起來簡單而直截了當?人們希望看到瀏覽器緩存圖像。但儘管嘗試所有組合Cache-Control,Expires,Last-Modified-OnETag,我沒有成功。

下面是兩個連續請求期間吐出的HTTP標頭(不相關的標頭刪除)。

GET /adarshr-web/assets/Acer.png HTTP/1.1 
Host: localhost:8080 
Pragma: no-cache 
Cache-Control: no-cache 

HTTP/1.1 200 OK 
Cache-Control: max-age=1209600 
Last-Modified: Sun, 21 Jul 2013 11:56:32 GMT 
Content-Type: image/png 
Date: Tue, 23 Jul 2013 21:22:58 GMT 
---------------------------------------------------------- 

GET /adarshr-web/assets/Acer.png HTTP/1.1 
Host: localhost:8080 
If-Modified-Since: Sun, 21 Jul 2013 11:56:32 GMT 
Cache-Control: max-age=0 

HTTP/1.1 200 OK <-- Why not 304 Not Modified? 
Cache-Control: max-age=1209600 
Last-Modified: Sun, 21 Jul 2013 11:56:32 GMT 
Content-Type: image/png 
Date: Tue, 23 Jul 2013 21:23:03 GMT 

然而,當我嘗試在網址如

我看到這些標頭(如Facebook URL)顯示響應正被瀏覽器緩存。

GET /rsrc.php/v2/yI/r/0PsXdTWc41M.png HTTP/1.1 
Host: fbstatic-a.akamaihd.net 
Pragma: no-cache 
Cache-Control: no-cache 

HTTP/1.1 200 OK 
Content-Type: image/png 
Last-Modified: Sat, 15 Jun 2013 00:48:42 GMT 
Cache-Control: public, max-age=31535893 
Expires: Wed, 23 Jul 2014 21:27:47 GMT 
Date: Tue, 23 Jul 2013 21:29:34 GMT 
---------------------------------------------------------- 

GET /rsrc.php/v2/yI/r/0PsXdTWc41M.png HTTP/1.1 
Host: fbstatic-a.akamaihd.net 
If-Modified-Since: Sat, 15 Jun 2013 00:48:42 GMT 
Cache-Control: max-age=0 

HTTP/1.1 304 Not Modified <-- Note this 
Content-Type: image/png 
Last-Modified: Sat, 15 Jun 2013 00:48:42 GMT 
Cache-Control: public, max-age=31535892 
Expires: Wed, 23 Jul 2014 21:27:47 GMT 
Date: Tue, 23 Jul 2013 21:29:35 GMT 

注:

  • 我沒有在我的Spring配置的<mvc:resources />節,因爲我做的完全一樣在我的控制器。即使添加它也沒有任何區別。
  • 由於上述原因,我沒有在Spring配置中再次定義的org.springframework.web.servlet.mvc.WebContentInterceptor。我曾嘗試添加一個沒有收益。
  • 我嘗試了所有在https://developers.google.com/speed/docs/best-practices/caching中解釋的方法。
  • 我可以在所有瀏覽器中複製此內容。
+0

我應該實現與'asset.getModifiedOn'值進行比較'的If-Modified-Since'請求頭值並返回304的邏輯?這是不是太低級? – adarshr

+2

你必須實現最後修改的檢查,幸運的是,Spring使得這很容易:http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html #mvc-ann-lastmodified –

+0

@Devon_C_Miller是的,這似乎是個伎倆。你可以把它作爲答案發布,以便我可以獎勵你嗎? – adarshr

回答

4

你必須執行最後修改的檢查,幸運的是,Spring使得這很容易。

Spring Framework Reference

@RequestMapping 
public String myHandleMethod(WebRequest webRequest, Model model) { 

    long lastModified = // 1. application-specific calculation 

    if (request.checkNotModified(lastModified)) { 
     // 2. shortcut exit - no further processing necessary 
     return null; 
    } 

    // 3. or otherwise further request processing, actually preparing content 
    model.addAttribute(...); 
    return "myViewName"; 
}