Ehcache
一、Ehcache的结构设计概览:
二、核心定义:
CacheManager:缓存管理器,以前是只允许单例的,不过现在也可以多实例了
cache:缓存管理器内可以放置若干cache,存放数据的实质,所有cache都实现了Ehcache接口
element:单条缓存数据的组成单位
system of record(SOR):可以取到真实数据的组件,可以是真正的业务逻辑、外部接口调用、存放真实数据的数据库等等,缓存就是从SOR中读取或者写入到SOR中去的。
三、ehcache.xml配置文件介绍(普通缓存)
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
maxBytesLocalDisk="20G" maxBytesLocalHeap="10M">
<!-- 指定一个文件目录,当EHCache把数据写到硬盘上时,将把数据写到这个文件目录下 -->
<diskStore path="java.io.tmpdir"/>
<!-- 设定缓存的默认数据过期策略 -->
<defaultCache maxElementsInMemory="10000" eternal="false" overflowToDisk="true" timeToIdleSeconds="0"
timeToLiveSeconds="0" diskPersistent="false" diskExpiryThreadIntervalSeconds="120"/>
<!-- 设定具体的命名缓存的数据过期策略
cache元素的属性:
name:缓存名称
maxElementsInMemory:内存中最大缓存对象数
maxElementsOnDisk:硬盘中最大缓存对象数,若是0表示无穷大
eternal:true表示对象永不过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds属性,默认为false
overflowToDisk:true表示当内存缓存的对象数目达到了maxElementsInMemory界限后,会把溢出的对象写到硬盘缓存中。注意:如果缓存的对象要写入到硬盘中的话,则该对象必须实现了Serializable接口才行。
diskSpoolBufferSizeMB:磁盘缓存区大小,默认为30MB。每个Cache都应该有自己的一个缓存区。
diskPersistent:是否缓存虚拟机重启期数据
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认为120秒
timeToIdleSeconds: 设定允许对象处于空闲状态的最长时间,以秒为单位。当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清空。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限期地处于空闲状态
timeToLiveSeconds:设定对象允许存在于缓存中的最长时间,以秒为单位。当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清除。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性,才有意义
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。 -->
<cache name="CACHE1" maxElementsInMemory="1000" eternal="true" overflowToDisk="true"/>
<cache name="CACHE2" maxElementsInMemory="1000" eternal="false" timeToIdleSeconds="200" timeToLiveSeconds="4000"
overflowToDisk="true"/>
</ehcache>
四、配置文件介绍(分布式缓存)
1)RMI集群模式
A、手工发现
需要指定节点发现模式peerDiscovery值为manual,rmiUrls设置为另一台服务器的IP、端口和缓存名等信息。
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual, rmiUrls=//192.168.0.12:4567/oschina_cache|//192.168.0.13:4567/oschina_cache" />
B、自动发现
需要指定节点发现模式peerDiscovery值为automatic自动,同时组播地址可以指定D类IP地址空间,范围从 224.0.1.0 到 238.255.255.255 中的任何一个地址。
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
multicastGroupPort=4446, timeToLive=32"
/>
五、通过编程的方式使用Ehcache
//从classes目录中查找ehcache.xml配置文件,这里会默认找ehcache.xml当然我们也可以指定路径
// CacheManager manager = new CacheManager("src/config/other.xml");
CacheManager cacheManager=CacheManager.getInstance();
//根据配置文件获Cache实例,这里是根据ehcache.xml中的name属性
Cache cache=cacheManager.getCache("CACHE1");
//清空cache中的所用元素
cache.removeAll();
//往cache中添加元素,这里的Element相当于HashMap中的键值对Entry<K,V>;
cache.put(new Element("s1","1111"));
cache.put(new Element("s2","2222"));
//从cache中取得元素
Element e=cache.get("s2");
System.out.println(e.getValue());
//卸载缓存管理器
cacheManager.shutdown();
六、页面缓存:
1、 在web.xml文件中配置过滤器。此处demo.jsp页面进行缓存。
<filter>
<filter-name>testPageCachingFilter</filter-name>
<filter-class>net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>testPageCachingFilter</filter-name>
<url-pattern>/demo.jsp</url-pattern>
</filter-mapping>
2、在ehcache.xml文件中配置Cache节点。注意:cache的name属性必需为SimplePageCachingFilter。
<cache name="SimplePageCachingFilter"
maxElementsInMemory="10"
overflowToDisk="true"
eternal="false"
timeToIdleSeconds="100"
timeToLiveSeconds="100"
memoryStoreEvictionPolicy="LFU" />
下面是一个实例:
package com.spring.cache;
import static org.junit.Assert.assertTrue;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.pool.Pool;
import org.slf4j.Logger;
public class TestDefaultCache {
private Logger Log;
//测试类
public static void main(String[] args) {
TestDefaultCache.cacheLocate("C:\\DATA\\cache");
}
// 使用缓存的基本操作
public static void testDefault(){
//从classes目录中查找encache.xml配置文件
CacheManager cacheManager=CacheManager.getInstance();
//根据配置文件获Cache实例
Cache cache=cacheManager.getCache("test");
//清空cache中的所用元素
cache.removeAll();
//往cache中添加元素,这里的Element相当于HashMap中的键值对Entry<K,V>;
cache.put(new Element("s1","1111"));
cache.put(new Element("s2","2222"));
System.out.println("calculateOnDiskSize: "+cache.calculateOnDiskSize());
System.out.println("MemoryStoreSize: "+cache.getMemoryStoreSize());
assertTrue(cache.getMemoryStoreSize() + cache.calculateOnDiskSize() == 2);
//System.out.println("MemoryStoreSize: "+cache.get);
//从cache中取得元素
Element e=cache.get("s2");
System.out.println(e.getValue());
//输出当前cacheManager正在使用的配置对应的Xml格式文本
System.out.println(cacheManager.getActiveConfigurationText());
//卸载缓存管理器
cacheManager.shutdown();
}
//将缓存写到本地硬盘上指定的位置。
public static void cacheLocate(String targetlocate){
/*系统默认的缓存地址可以在System.getProperty(String key)方法中找到,其中key为java.io.tmpdir
* 这里我们也可以通过 System.setProperty("java.io.tmpdir", "C:\\DATA\\cache");这个方法去改变我们想缓存的地方
* */
System.out.println(System.getProperty("java.io.tmpdir"));
System.setProperty("java.io.tmpdir", targetlocate);//设置缓存的位置
System.out.println(System.getProperty("java.io.tmpdir"));
CacheManager cacheManager=new CacheManager();
Cache cache=cacheManager.getCache("simpleCache");
for(int i=0;i<5;i++){
Element element=new Element("key"+i,"myvalue"+i);
cache.put(element);
}
cache.flush();
System.out.println("已经成功缓存");
//===============================================================================================
System.out.println("=============================读取cache=================================");
System.out.println("DiskStoreSize:"+cache.getDiskStoreSize());
System.out.println("MemoryStoreSize:"+cache.getMemoryStoreSize());
String [] strs=cacheManager.getCacheNames();//拿到所有cache名字
for (String str : strs) {
System.out.println(str);
}
cacheManager.shutdown();
}
}
Ehcache.xml
<!-- <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
maxBytesLocalDisk="20G" maxBytesLocalOffHeap="50M"
>
<diskStore path="java.id.tmpdir"/>
<defaultCache copyOnRead="true" copyOnWrite="true" overflowToOffHeap="false"></defaultCache>
<cache name="test" maxBytesLocalHeap="10M"/>
<cache name="test2" overflowToOffHeap="false" maxBytesLocalHeap="10M"></cache>
<cache name="sampleCache" maxElementsInMemory="10000" maxElementsOnDisk="1000" eternal="false"
overflowToDisk="true" diskSpoolBufferSizeMB="20"
timeToIdleSeconds="300" timeToLiveSeconds="600" memoryStoreEvictionPolicy="FIFO" />
</ehcache> -->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="java.io.tmpdir"/>
<Cache name="test" maxElementsInMemory="1000"></Cache>
<!-- 缓存到本地硬盘上 -->
<Cache name="simpleCache"
maxElementsInMemory="2"
eternal="false"
timeToIdleSeconds="600"
timeToLiveSeconds="300"
overflowToDisk="true"
maxElementsOnDisk="3"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="FIFO"
/>
<!--
<Cache name="simpleCache" 缓存的名字
maxElementsInMemory="10000" 内存中最大的对象数
eternal="false" 对象是否永久存活
timeToIdleSeconds="120" 最大的空闲时间
timeToLiveSeconds="120" 最长的活跃时间
overflowToDisk="true" 当大小超过memory的大小时,可以缓存到本地硬盘
maxElementsOnDisk="10000000" 硬盘上最大的对象数
diskPersistent="false" 是否在硬盘上持久化保存
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU" 内存清除对象的方式
/> -->
</ehcache>