2011-02-25 111 views

回答

5

你可以做這個工作,但我認爲有更好的解決方案。

首先,如果你想使用Spring MVC的攔截器,你將使用的postHandle方法來存儲您的緩存和preHandle東西檢查緩存和可能的規避處理。問題是,你在緩存中存儲什麼。您需要存儲完整的回覆。這意味着您將不得不在PostHandle中輕鬆獲得ModelAndView的完整響應。這可能也可能不容易,這取決於你如何做事。

您最好使用不同的緩存機制。我建議在Web服務器級別緩存。如果您希望在攔截器級別緩存,那麼這是尤其真實的,因爲這對於Web服務器而言是「下一個」,我認爲在那裏重新發明輪子沒有任何好處。 Apache有一個緩存模塊。 nginx也是如此。清漆也非常棒。

我還要提到的是,你不應該緩存,直到你確定你需要(不要過早優化)。這是浪費你的時間和精力。其次,當你確定你確實有需要修復的性能問題(並且緩存是正確的解決方案)時,你應該將正確的數據緩存在正確的位置。

現在,假設你確定你有一個性能問題和某種形式的緩存是一個很好的解決方案。接下來要確定的是可以緩存的內容。如果每個URL都返回相同的數據,那麼緩存在Web服務器(Apache,nginx,Varnish等)級別將是您最好的選擇。

通常情況下,您將遇到兩個客戶端將訪問相同URL並獲取不同數據的情況。這在Facebook等網站上最容易看到。我登錄時看到的數據不同於我的朋友看到​​的數據。在這種情況下,您將無法在Web服務器級別緩存。您將需要在應用程序內緩存。通常這意味着在數據庫級別進行緩存。

0

在應用程序級別,我會使用普通Java緩存作爲EHCache。 EHCache很容易與Spring bean上的方法集成。您可以將您的服務方法註釋爲@Cacheable並完成。請在EHCache Spring Annotations查看。

在HTTP級別,Spring MVC中提供了一個有用的ETag filter。但是我認爲如果你能夠在服務器級別配置這種緩存比應用程序級別更好。

4

我不能不同意解決方案的優化部分。

當您從遠程位置(可能在幾千英里之外)加載數據時,Web請求本質上很慢。每個呼叫必須承受至少數據包本身的完整TCP往返時間,可能是每個請求的連接和鰭,在開始傳輸數據之前,連接是三包同步交換。

美國海岸到西海岸的延遲是一個很好的一天50ms左右,所以每一個連接遭受懲罰時間150ms,這對於大多數實現中發生的每一個請求。

緩存在客戶端的響應完全消除這種延遲,如果服務對他們的反應正確的標題,實在是微不足道。如果他們不這樣做,你就必須定義一個緩存策略,這在大多數情況下並不是特別困難。大多數API調用都是實時的或不是。

在我看來,緩存REST響應不是過早優化,這是常識。

+0

更多的細節將 – 2015-07-30 22:53:04

-1

從Spring 3.1開始,您可以使用@Cachable註釋。還支持條件緩存,以及一些同級註釋,如@CachePut,@CacheEvict@Caching,以獲得更細粒度的控制。

Spring目前支持兩種不同的cache managers,一種支持ConcurrentHashMap,另一種支持Ehcache

最後,別忘了閱讀關於如何註釋的詳細信息。

2

我使用它,它可以以超棒的速度工作。 真的使用方便彈簧+ ehcache的:

1)控制器:

@Cacheable("my.json") 
    @RequestMapping("/rest/list.json") 
    public ResponseEntity list(@RequestParam(value = "page", defaultValue = "0", required = false) 
           int pageNum, 
           @RequestParam(value = "search", required = false) 
           String search) throws IOException { 
    ... 
    } 

2)在一些ehcache.xml中是這樣的:

<cache name="my.json" maxElementsInMemory="10000" eternal="true" overflowToDisk="false"/> 

3)配置彈簧。我使用spring javaconf樣式:

@Configuration 
@EnableCaching 
public class ApplicationConfiguration { 


    @Bean 
    public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() throws MalformedURLException { 
     EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean(); 
     ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml")); 
     return ehCacheManagerFactoryBean; 
    } 

    @Bean 
    @Autowired 
    public EhCacheCacheManager cacheManager(EhCacheManagerFactoryBean ehcache) { 
     EhCacheCacheManager ehCacheCacheManager = new EhCacheCacheManager(); 
     ehCacheCacheManager.setCacheManager(ehcache.getObject()); 
     return ehCacheCacheManager; 
    } 
} 
+2

這不能工作有用。 ResponseEntity不是可序列化的,並且該應用程序會拋出異常 – Dan 2015-11-24 00:52:04

+0

@ Dan與ResponseEntity hakamairi 2017-09-19 08:17:45

0

不要使用彈簧緩存它不是你所需要的。您需要減少服務器的負載,而不是加速內部彈簧應用程序的執行。

嘗試使用som與HTTP相關的緩存策略。

您可以添加HTTP報頭的一個對您的請求

#cache expires in 3600 seconds 
cache-control: private, max-age=3600 

#hash of your content 
ETag: "e6811cdbcedf972c5e8105a89f637d39-gzip" 

# redirect caching to any HTTP header 
vary: User-Agent 

Detailed description of caching techniques

春例如

@RequestMapping (value = "/resource/1.pdf", produces = "application/octet-stream") 
public ResponseEntity<InputStreamResource> getAttachement (@RequestParam (value = "id") Long fileId) 
{ 
    InputStreamResource isr = new InputStreamResource(javaInputStream); 
    HttpHeaders headers = new HttpHeaders(); 
    //other headers 
    headers.setCacheControl("private, max-age=3600"); 
    return new ResponseEntity<>(irs, headers, HttpStatus.OK); 

}