這里的cache storage 采用ehcache,而不是默認的內存式的cache storage。采用ehcache可以將內容緩存到磁盤上。
maven
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient-cache</artifactId> <version>4.5</version> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.8.3</version> </dependency>
ehcache配置如下:
<ehcache> <!-- <diskStore path="java.io.tmpdir" /> --> <diskStore path="c:\\ehcache"/> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> <cache name="httpCache" maxElementsInMemory="10000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="true" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> </ehcache>
這里有兩個關鍵點:一是將eternal設置為true,表示采用非內存式的緩存;二是將diskPersistent設置為true,表示將緩存持久化到硬盤。
測試的代碼如下:
package my.httpClient; import java.io.IOException; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.config.CacheConfiguration; import net.sf.ehcache.config.Configuration; import net.sf.ehcache.config.DiskStoreConfiguration; import net.sf.ehcache.config.PersistenceConfiguration; import net.sf.ehcache.config.PersistenceConfiguration.Strategy; import net.sf.ehcache.store.MemoryStoreEvictionPolicy; import org.apache.http.HttpHost; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.cache.CacheResponseStatus; import org.apache.http.client.cache.HttpCacheContext; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.cache.CacheConfig; import org.apache.http.impl.client.cache.CachingHttpClients; import org.apache.http.impl.client.cache.ehcache.EhcacheHttpCacheStorage; public class EhCacheTest1 { public static void main(String[] args) throws ClientProtocolException, IOException { System.out.println("begin"); // EhCache緩存存儲 CacheManager cacheManager = CacheManager.create(); Cache httpCache = cacheManager.getCache("httpCache"); // 定義httpclient的緩存存儲 EhcacheHttpCacheStorage ehcacheHttpCacheStorage = new EhcacheHttpCacheStorage( httpCache); // 緩存配置 CacheConfig cacheConfig = CacheConfig.custom() .setMaxCacheEntries(10000).setMaxObjectSize(819200).build(); RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(30000).setSocketTimeout(30000).build(); HttpHost proxy = new HttpHost("127.0.0.1", 8888); CloseableHttpClient cachingClient = CachingHttpClients.custom() .setCacheConfig(cacheConfig) .setHttpCacheStorage(ehcacheHttpCacheStorage) .setDefaultRequestConfig(requestConfig).setProxy(proxy).build(); HttpCacheContext context = HttpCacheContext.create(); HttpGet httpget = new HttpGet("http://test.cn:11677/api/values?id=8888"); CloseableHttpResponse response = cachingClient .execute(httpget, context); try { CacheResponseStatus responseStatus = context .getCacheResponseStatus(); switch (responseStatus) { case CACHE_HIT: System.out .println("A response was generated from the cache with " + "no requests sent upstream"); break; case CACHE_MODULE_RESPONSE: System.out .println("The response was generated directly by the " + "caching module"); break; case CACHE_MISS: System.out.println("The response came from an upstream server"); break; case VALIDATED: System.out.println("The response was generated from the cache " + "after validating the entry with the origin server"); break; } } catch (Exception e) { // TODO: handle exception } finally { response.close(); cacheManager.shutdown(); System.out.println("end"); } } }
以上代碼有幾個需要說明的地方:
(1)服務端需要遵循RFC2626中規定緩存方面的協議。
(2)代碼setHttpCacheStorage(ehcacheHttpCacheStorage)用於設置緩存存儲。
(3)代碼setProxy(proxy)用於配置代理,當你使用fiddler進行調試的時候,這個很有用。若不采用代理,則可以將這句給去掉。
(4)代碼cacheManager.shutdown()用於關閉cacheManager,記得一定要執行這一句,否則會報錯。