日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

EHCache讲解

發(fā)布時(shí)間:2025/3/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 EHCache讲解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

EHCache是來(lái)自sourceforge(http://ehcache.sourceforge.net/)的開(kāi)源項(xiàng)目,也是純Java實(shí)現(xiàn)的簡(jiǎn)單、快速的Cache組件。EHCache支持內(nèi)存和磁盤的緩存,支持LRU、LFU和FIFO多種淘汰算法,支持分布式的Cache,可以作為Hibernate的緩存插件。同時(shí)它也能提供基于Filter的Cache,該Filter可以緩存響應(yīng)的內(nèi)容并采用Gzip壓縮提高響應(yīng)速度。

1. EHCache API的基本用法

1.1 CacheManager類

作用:主要負(fù)責(zé)讀取配置文件,并根據(jù)配置文件創(chuàng)建和管理Cache類。默認(rèn)讀取CLASSPATH下的ehcache.xml。

// 使用默認(rèn)配置文件創(chuàng)建CacheManager CacheManager manager = CacheManager.create(); // 通過(guò)manager可以生成指定名稱的Cache對(duì)象 Cache cache = cache = manager.getCache("myCache"); // 使用manager移除指定名稱的Cache對(duì)象 manager.removeCache("myCache"); //可用來(lái)移除所有的Cache manager.removalAll(); //關(guān)閉CacheManager manager.shutdown();

1.2 Cache類

//往cache中添加元素 Element element = new Element("key", "value"); cache.put(element); //從cache中取回元素 Element element = cache.get("key"); element.getValue(); //從Cache中移除一個(gè)元素 cache.remove("key");

注意:對(duì)于緩存的對(duì)象必須是可序列化的。

1.3 配置文件

配置文件ehcache.xml中命名為myCache的緩存配置:

<cache name="myCache" //該名字與manager里操作的名字一樣maxElementsInMemory="10000" // 緩存中允許創(chuàng)建的最大對(duì)象數(shù)eternal="false" //緩存中對(duì)象是否為永久。如果是,超時(shí)設(shè)置將被忽略,對(duì)象從不過(guò)期。overflowToDisk="true" //內(nèi)存不足時(shí),是否啟用磁盤緩存timeToIdleSeconds="300" //緩存數(shù)據(jù)的鈍化時(shí)間,即在一個(gè)元素消亡之前,兩次訪問(wèn)時(shí)間的最大時(shí)間間隔值。這只能在元素不是永久駐留時(shí)有效,如果該值是 0 就意味著元素可以停頓無(wú)窮長(zhǎng)的時(shí)間。timeToLiveSeconds="600" //緩存數(shù)據(jù)的生存時(shí)間,也就是一個(gè)元素從構(gòu)建到消亡的最大時(shí)間間隔值。這只能在元素不是永久駐留時(shí)有效,如果該值是0就意味著元素可以停頓無(wú)窮長(zhǎng)的時(shí)間。memoryStoreEvictionPolicy="LFU" //緩存滿了之后的淘汰算法。LFU算法直接淘汰使用比較少的對(duì)象,在內(nèi)存保留的都是一些經(jīng)常訪問(wèn)的對(duì)象。對(duì)于大部分網(wǎng)站項(xiàng)目,該算法比較適用。/>

如果應(yīng)用需要配置多個(gè)不同命名并采用不同參數(shù)的Cache,可以相應(yīng)修改配置文件,增加需要的Cache配置即可。

2. 利用Spring APO整合EHCache

首先,在CLASSPATH下面放置ehcache.xml配置文件。在Spring的配置文件中先添加如下cacheManager配置:

<bean id="cacheManager1" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"><property name="configLocation"><value>classpath:ehcache.xml</value></property> </bean> // 配置myCache: <bean id="myCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"><property name="cacheManager" ref="cacheManager1" /><property name="cacheName"><value>myCache</value> <!-- 在咖啡 --></property> </bean>

接下來(lái),寫一個(gè)實(shí)現(xiàn)org.aopalliance.intercept.MethodInterceptor接口的攔截器類。
有了攔截器就可以有選擇性的配置想要緩存的 bean 方法。如果被調(diào)用的方法配置為可緩存,攔截器將為該方法生成 cache key 并檢查該方法返回的結(jié)果是否已緩存。如果已緩存,就返回緩存的結(jié)果,否則再次執(zhí)行被攔截的方法,并緩存結(jié)果供下次調(diào)用。具體代碼如下:

public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean {private Cache cache;public void setCache(Cache cache) {this.cache = cache;}public void afterPropertiesSet() throws Exception {Assert.notNull(cache,"A cache is required. Use setCache(Cache) to provide one.");}public Object invoke(MethodInvocation invocation) throws Throwable {String targetName = invocation.getThis().getClass().getName();String methodName = invocation.getMethod().getName();Object[] arguments = invocation.getArguments();Object result;String cacheKey = getCacheKey(targetName, methodName, arguments);Element element = null;/**為什么一定要同步?Cache對(duì)象本身的get和put操作是同步的。如果我們緩存的數(shù)據(jù)來(lái)自數(shù)據(jù)庫(kù)查詢,在沒(méi)有這段同步代碼時(shí),當(dāng)key不存在或者key對(duì)應(yīng)的對(duì)象已經(jīng)過(guò)期時(shí),在多線程并發(fā)訪問(wèn)的情況下,許多線程都會(huì)重新執(zhí)行該方法,由于對(duì)數(shù)據(jù)庫(kù)進(jìn)行重新查詢代價(jià)是比較昂貴的,同步后,如果一個(gè)線程從數(shù)據(jù)庫(kù)拿到了數(shù)據(jù),則后面的線程不需要去數(shù)據(jù)庫(kù)再查詢了。*/synchronized (this){element = cache.get(cacheKey);if (element == null) {//調(diào)用實(shí)際的方法result = invocation.proceed();element = new Element(cacheKey, (Serializable) result);cache.put(element);}}return element.getValue();}private String getCacheKey(String targetName, String methodName,Object[] arguments) {StringBuffer sb = new StringBuffer();sb.append(targetName).append(".").append(methodName);if ((arguments != null) && (arguments.length != 0)) {for (int i = 0; i < arguments.length; i++) {sb.append(".").append(arguments[i]);}}return sb.toString();} }

接下來(lái),完成攔截器和Bean的配置:

<bean id="methodCacheInterceptor" class="com.xiebing.utils.interceptor.MethodCacheInterceptor"><property name="cache"><ref local="myCache" /></property> </bean> <bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"><property name="advice"><ref local="methodCacheInterceptor" /></property><property name="patterns"><list><!-- 所有以myMethod結(jié)尾的方法都會(huì)被緩存 --><value>.*myMethod</value></list></property> </bean><bean id="myServiceBean" class="com.xiebing.ehcache.spring.MyServiceBean"> </bean><bean id="myService" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target"><ref local="myServiceBean" /></property><property name="interceptorNames"><list><value>methodCachePointCut</value></list></property> </bean>

使用AOP的方式極大地提高了系統(tǒng)的靈活性,通過(guò)修改配置文件就可以實(shí)現(xiàn)對(duì)方法結(jié)果的緩存,所有的對(duì)Cache的操作都封裝在了攔截器的實(shí)現(xiàn)中。

3. CachingFilter功能

作用:可以對(duì)HTTP響應(yīng)的內(nèi)容進(jìn)行緩存。這種方式緩存數(shù)據(jù)的粒度比較粗,例如緩存整張頁(yè)面。
優(yōu)點(diǎn):使用簡(jiǎn)單、效率高
缺點(diǎn):不夠靈活,可重用程度不高。
EHCache使用SimplePageCachingFilter類實(shí)現(xiàn)Filter緩存。該類繼承自CachingFilter,有默認(rèn)產(chǎn)生cache key的calculateKey()方法,該方法使用HTTP請(qǐng)求的URI和查詢條件來(lái)組成key。也可以自己實(shí)現(xiàn)一個(gè)Filter,同樣繼承CachingFilter類,然后覆寫calculateKey()方法,生成自定義的key。
有時(shí)在使用AJAX時(shí),為保證JS請(qǐng)求的數(shù)據(jù)不被瀏覽器緩存,每次請(qǐng)求都會(huì)帶有一個(gè)隨機(jī)數(shù)參數(shù)i。如果使用SimplePageCachingFilter,那么每次生成的key都不一樣,緩存就沒(méi)有意義了。這種情況下,我們就會(huì)覆寫calculateKey()方法。
要使用SimplePageCachingFilter,首先在配置文件ehcache.xml中,增加下面的配置:

<filter><filter-name>SimplePageCachingFilter</filter-name><filter-class>net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter</filter-class> </filter> <filter-mapping><filter-name>SimplePageCachingFilter</filter-name><url-pattern>/test.jsp</url-pattern> </filter-mapping>

下面我們寫一個(gè)簡(jiǎn)單的test.jsp文件進(jìn)行測(cè)試,緩存后的頁(yè)面每次刷新,在600秒內(nèi)顯示的時(shí)間都不會(huì)發(fā)生變化的。代碼如下:

<% out.println(new Date()); %>

CachingFilter輸出的數(shù)據(jù)會(huì)根據(jù)瀏覽器發(fā)送的Accept-Encoding頭信息進(jìn)行Gzip壓縮。經(jīng)過(guò)測(cè)試,Gzip壓縮后的數(shù)據(jù)量是原來(lái)的1/4,速度是原來(lái)的4-5倍,所以緩存加上壓縮,效果非常明顯。

在使用Gzip壓縮時(shí),需注意兩個(gè)問(wèn)題:
1. Filter在進(jìn)行Gzip壓縮時(shí),采用系統(tǒng)默認(rèn)編碼,對(duì)于使用GBK編碼的中文網(wǎng)頁(yè)來(lái)說(shuō),需要將操作系統(tǒng)的語(yǔ)言設(shè)置為:zh_CN.GBK,否則會(huì)出現(xiàn)亂碼的問(wèn)題。
2. 默認(rèn)情況下CachingFilter會(huì)根據(jù)瀏覽器發(fā)送的請(qǐng)求頭部所包含的Accept-Encoding參數(shù)值來(lái)判斷是否進(jìn)行Gzip壓縮。雖然IE6/7瀏覽器是支持Gzip壓縮的,但是在發(fā)送請(qǐng)求的時(shí)候卻不帶該參數(shù)。為了對(duì)IE6/7也能進(jìn)行Gzip壓縮,可以通過(guò)繼承CachingFilter,實(shí)現(xiàn)自己的Filter,然后在具體的實(shí)現(xiàn)中覆寫方法acceptsGzipEncoding。
具體實(shí)現(xiàn)參考:

protected boolean acceptsGzipEncoding(HttpServletRequest request) {final boolean ie6 = headerContains(request, "User-Agent", "MSIE 6.0");final boolean ie7 = headerContains(request, "User-Agent", "MSIE 7.0");return acceptsEncoding(request, "gzip") || ie6 || ie7; }

4. EHCache在Hibernate中的使用

EHCache可以作為Hibernate的二級(jí)緩存使用。在hibernate.cfg.xml中需增加如下設(shè)置:

<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider </prop>

然后在Hibernate映射文件的每個(gè)需要Cache的Domain中,加入類似如下格式信息:

<cache usage="read-write|nonstrict-read-write|read-only" />

比如:

<cache usage="read-write" />

最后在配置文件ehcache.xml中增加一段cache的配置,其中name為該domain的類名。

<cache name="domain.class.name" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="false" />

5. EHCache的監(jiān)控

對(duì)于Cache的使用,除了功能,在實(shí)際的系統(tǒng)運(yùn)營(yíng)過(guò)程中,我們會(huì)比較關(guān)注每個(gè)Cache對(duì)象占用的內(nèi)存大小和Cache的命中率。有了這些數(shù)據(jù),我們就可以對(duì)Cache的配置參數(shù)和系統(tǒng)的配置參數(shù)進(jìn)行優(yōu)化,使系統(tǒng)的性能達(dá)到最優(yōu)。EHCache提供了方便的API供我們調(diào)用以獲取監(jiān)控?cái)?shù)據(jù),其中主要的方法有:

//得到緩存中的對(duì)象數(shù) cache.getSize(); //得到緩存對(duì)象占用內(nèi)存的大小 cache.getMemoryStoreSize(); //得到緩存讀取的命中次數(shù) cache.getStatistics().getCacheHits() //得到緩存讀取的錯(cuò)失次數(shù) cache.getStatistics().getCacheMisses()

6. 分布式緩存

EHCache從1.2版本開(kāi)始支持分布式緩存。分布式緩存主要解決集群環(huán)境中不同的服務(wù)器間的數(shù)據(jù)的同步問(wèn)題。具體的配置如下:
在配置文件ehcache.xml中加入

<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1, multicastGroupPort=4446"/><cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/>

另外,需要在每個(gè)cache屬性中加入

<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>

例如:

<cache name="demoCache" maxElementsInMemory="10000" eternal="true" overflowToDisk="true" ><cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/> </cache>

總結(jié)

EHCache是一個(gè)非常優(yōu)秀的基于Java的Cache實(shí)現(xiàn)。它簡(jiǎn)單、易用,而且功能齊全,并且非常容易與Spring、Hibernate等流行的開(kāi)源框架進(jìn)行整合。通過(guò)使用EHCache可以減少網(wǎng)站項(xiàng)目中數(shù)據(jù)庫(kù)服務(wù)器的訪問(wèn)壓力,提高網(wǎng)站的訪問(wèn)速度,改善用戶的體驗(yàn)。

總結(jié)

以上是生活随笔為你收集整理的EHCache讲解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。