J2EE Ehcache使用文档

以下内容转载自:http://wenku.baidu.com/view/6343f349f7ec4afe04a1df88.html
----------------------------------------正文分割线-------------------------------------------


 

Ehcache使用文档

 

 

 

                                      作者:兰东平

                                      Email:landongpingpub@163.com

 

 

 

 

2012年2月

 

 

 

 

 

 

1     基本介绍

1.1 前言

Ehcache是一个快速的、轻量级的、易于使用的、进程内的缓存。它支持read-only 和read/write 缓存,内存和磁盘缓存。是一个非常轻量级的缓存实现,而且从1.2 之后就支持了集群,目前的最新版本是2.5。

简单地说来,ehcache有以下特点:

l  快速.

l  简单.

l  多种缓存策略

l  缓存数据有两级:内存和磁盘,因此无需担心容量问题

l  缓存数据会在虚拟机重启的过程中写入磁盘

l  可以通过RMI、可插入API 等方式进行分布式缓存

l  具有缓存和缓存管理器的侦听接口

l  支持多缓存管理器实例,以及一个实例的多个缓存区域

l  提供Hibernate 的缓存实现

2     安装和使用

2.1 下载

Ehcache的官方网站http://ehcache.org/downloads/catalog上面可以下载到各种版本。目前用最新版本是2.5.1,下载这个版本即可。(下载之前,会要求用户注册,按照要求输入即可)。

建议下载ehcache-2.5.1-distribution.tar.gz文件,因为这个文件包含了所有Ehcache的内容。

2.2 安装

2.2.1 发布包内容说明

将ehcache-2.5.1-distribution.tar.gz解压到本地文件系统。在安装之前,我们先来大致看看发布包里边的内容,如下图2.1所示。

                            图2.1

如一般的开源框架发布包类似,ehcahce的发布包包含以下目录内容:

javadoc:ehcache的API文档;

lib:ehcache要用到的第三方jar包和自己的jar包;

licenses:ehcache的授权文件;

samples:ehcache的例子目录;

src:ehcache的源代码目录;

terracotta:使用terracotta集群时的terracotta服务;

ehcache.xml:ehcache的配置文件模板,包括各个配置的英文解释;

ehcache.xsd:ehcache.xml文件的验证文件模板;

QUICK-START.html:快速开始文件,会连接到ehcache的官方网站;

README.html:ehcache版本功能和新特性说明文件。

除了阅读本文档快速地学习和了解ehcache的功能,也可以通过ehcache自带的快速开始文件进行学习。

2.2.2 安装到项目工程

Ehcache的安装方法比较简单,将解压开的发布包下的lib /ehcache-core-2.5.1.jar、lib /slf4j-api-1.6.1.jar和lib/slf4j-jdk14-1.6.1.jar放置到类路径下面即可使用。如下图2.2所示:

                        图2.2

其中,slf4j-api-1.6.1.jar和slf4j-jdk14-1.6.1.jar两个jar包,用于ehcache的日志输出,是第三方jar包。关于这两个jar包的用法和功能特性,请查阅slf4j框架的相关功能。

3     开始一个例子

3.1 新建一个空的java project工程

通过eclipse向导新建一个Java Project工程ehcache-test,并将上面提的三个类添加到类路径下。工程如下图3.1所示:

           图3.1

其中的lib目录,我专门用来存放jar包。

 

3.2 工程中添加配置文件

3.2.1 新建配置文件存放目录

在ehcache-test工程中新建专门用于存放配置文件的包,根据我们的习惯,该包取名为“conf”。

3.2.2 加入ehcache配置文件

在刚才新建的conf包下加入发布包目录下的ehcache.xml和ehcache.xsd两个配置文件。(注意,这两个配置文件要放在同一目录下。如果需要将ehcache.xsd文件放到其他目录,需要修改ehcache.xml文件中的xsi:noNamespaceSchemaLocation="ehcache.xsd"配置项

经过以上步骤操作,工程目录结构如下图3.2所示:

3.2.3 修改ehcache.xml配置文件内容

正如先前所述,ehcache.xml是ehcache的配置文件模板,每一项配置的说明都相当详细。在修改该配置文件之前,如果大家有兴趣,不妨先大致看看其中的内容和注释。

为了说明简单,我们先运行ehcache最基本和简单的例子。配置文件内容如下:

<?xmlversion="1.0"encoding="UTF-8"?>

 

<ehcachexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:noNamespaceSchemaLocation="ehcache.xsd"updateCheck="false"

    monitoring="autodetect"dynamicConfig="true">

 

    <defaultCachemaxEntriesLocalHeap="0"eternal="false"

       overflowToDisk="true"timeToIdleSeconds="1200"timeToLiveSeconds="1200">

    </defaultCache>

 

    <cachename="sampleCache1"maxEntriesLocalHeap="10000"

       maxEntriesLocalDisk="1000"eternal="false"overflowToDisk="true"

       diskSpoolBufferSizeMB="20"timeToIdleSeconds="300"timeToLiveSeconds="600"

       memoryStoreEvictionPolicy="LFU"transactionalMode="off"/>

      

</ehcache>

经过以上步骤操作,我们的工程如下图3.2所示:

               图3.2

3.3 编写测试类

新建名为“ehcache”的包。在“ehcache”包下面新建“TestMain.java”类。

TestMain.java文件内容使用Junit来编写,所以我们还需要在工程中添加Junit4。TestMain.java的内容很简单,如下:

package ehcache;

 

import java.net.URL;

 

import junit.framework.TestCase;

import net.sf.ehcache.Cache;

import net.sf.ehcache.CacheManager;

import net.sf.ehcache.Element;

 

/**

 *

 * @authorldp

 *

 */

public class TestMain {

    @Test

public void testF1() throws Exception {

       URLurl = TestMain.class.getClassLoader().getResource(

              "conf/ehcache.xml");

       CacheManagermanager = new CacheManager(url);

 

       Cachecache1 = manager.getCache("sampleCache1");

       Stringkey = "key1";

       Stringvalue =key.hashCode() +"";

 

       Elementelement1 = new Element(key,value);

       cache1.put(element1);

       System.out.println(cache1.get(key));

      

       manager.shutdown();

    }

}

以上是一个很简单的测试类,稍后我们再对代码进行分析。

3.4 运行测试类

运行上面的TestMain.java类,输出结果如下:

3.5 代码解析

下面主要对TestMain.java中的testF1()方法进行详细地解析。

代码片段1:

       URLurl = TestMain.class.getClassLoader().getResource(

              "conf/ehcache.xml");

   CacheManager manager = new CacheManager(url);

这两行代码根据conf/ehcache.xml配置文件新建出一个CacheManager对象。也就是说,一个ehcache.xml文件就对应一个CacheManager对象,ehcache.xml中配置的各个缓存,即为该CacheManager对象实际管理和控制的cache对象。

代码片段2:

Cache cache1 =manager.getCache("sampleCache1");

通过CacheManager对象获取其中的指定缓存(sampleCache1)。每个缓存以其name属性来区分。

代码片段3:

       Stringkey = "key1";

   String value = key.hashCode() + "";

新建一个键值对。

代码片段4:

       Elementelement1 = new Element(key, value);

       cache1.put(element1);

   System.out.println(cache1.get(key));

新建一个Element对象,该对象以刚才的键值对为数据;再将Element对象放入到缓存sampleCache1中;再从缓存sampleCache1中根据键取出存入其中的Element对象。

代码片段5:

manager.shutdown();

关闭CacheManager对象,程序运行结束。

4     Ehcache的基本原理

通过以上的一个简单的例子,我们已经大体了解了一些Ehcache的原理。接下来,我们再比较详细地了解下Ehcache的原理。

4.1 整体结构

 Ehcache的类层次模型主要为三层,最上层的是CacheManager,他是操作Ehcache的入口。我们可以通过CacheManager.getInstance()获得一个单个的CacheManager,或者通过CacheManager的构造函数创建一个新的CacheManager。每个CacheManager都管理着多个Cache。而每个Cache都以一种类Hash的方式,关联着多个Elemenat。而Element则是我们用于存放要缓存内容的地方。

Ehcache的整体结构图如下图4.1所示。

                             图4.1

ehcache的刷新策略

ehcache的刷新策略是当缓存在放入的时候记录一个放入时间,它是用Lazy Evict的方式,在取的时候同设置的TTL比较。

ehcache缓存的3种清空策略:

Ø  FIFO,先进先出

Ø  LFU,最少被使用,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。

Ø  LRU,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。

事件处理

可以为CacheManager添加事件监听,当对CacheManager增删Cache时,事件处理器将会得到通知。要配置事件处理,需要通过ehcache的配置文件来完成。

可以为Cache添加事件监听,当对Cache增删Element时,事件处理器将会得到通知。要配置事件处理,需要通过ehcache的配置文件来完成。

4.2 CacheManager

如上文所述,CacheManager是操作Ehcache的入口。其类结构如下:

对于CacheManager,我么重点了解它的构造函数。我们可以有两种模式来创建CacheManager,单例(Singleton)和多例(Instance)。

单例创建CacheManager是指通过CacheManager.getInstance()方法或者无参的构造函数CacheManager()创建一个CacheManager对象。这种情况下,系统会在最顶层的classpath路径下找名叫ehcache.xml的配置文件,如果查找失败,会以ehcache-core-2.5.1.jar包中的ehcache-failsafe.xml文件(里边的缓存配置极其简单)替代。同时,一个警告会提醒用户建立自己的配置文件。

测试代码(添加在ehcache-test工程的TestMain.java中,以下同是):

    @Test

public void testF2() throwsException {

       CacheManagermanager = new CacheManager();

manager.addCache("sampleCache1");

       Cachecache1 = manager.getCache("sampleCache1");

       Stringkey = "key1";

       Stringvalue = key.hashCode() + "";

       Elementelement1 = new Element(key, value);

       cache1.put(element1);

       System.out.println(cache1.get(key));

       manager.shutdown();

   }

执行结果如下图4.2所示:

                               图4.2

同时,我们也可以看到,当我们用代码“manager.addCache("sampleCache1");”向CacheManager中加入缓存时,系统会自动用ehcache-failsafe.xml中的<defaultCache>项的配置创建出一个name为“sampleCache1”的cache。

多例创建CacheManager的方法和先前的testF1()方法一致。CacheManager支持多种方式创建:Configuration对象、InputStream对象、配置文件路径字符串和URL对象。如果大家有兴趣,都可以去尝试一下。

特别地,对于多例创建CacheManager,我们需要指定CacheManager的name属性,系统不允许多个相同name的CacheManager存在;另外,对于一些资源,如当设置了cache内存占用空间满了后,就将缓存数据存放到物理硬盘上(Cache的overflowToDisk属性),每个CacheManager对象的diskStore配置路径不能有重复。关于diskStore的详细配置说明,请参照ehcache.xml模板文件。

4.3 Ehcache接口

所有的cache都实现此接口,每个cache有自己的name和其他属性,cache中存放Element对象数据。Cache中的Element对象一般存储在MemoryStore里边,我们也可以配置将其存储到DiskStore配置指定的文件路径下边。该接口的结构如下:

4.4 Element

Element对象是存储在cache对象中的最基本元素,主要由键、值和访问记录三部分信息要素构成。

如果cache的配置只是让Element存放在MemoryStore中,对Element对象存储的值没有特殊要求;如果cache配置让Element对象存放在DiskStore中,或者在集群环境里cache信息复制时,则要求Element对象存储的值是可序列化的(Serializable)。如果不可序列化的对象被放到DiskStore中,或者集群中复制,则这些信息将被丢失,不会有error产生,只产生debug级别的日志。

Element类的结构如下所示:

 

5     集群环境下使用缓存

Ehcache支持多种集群环境下的使用。不同的集群环境,ehcache.xml的配置不一样。

Ehcache支持以下五种集群方式:

l Terracotta

l RMI

l JMS

l JGroups

l EhCache Server

我们主要看最常用的一种方式:RMI。

5.1 RMI 集群模式

RMI 是 Java 的一种远程方法调用技术,是一种点对点的基于 Java 对象的通讯方式。EhCache 从 1.2 版本开始就支持 RMI 方式的缓存集群。在集群环境中 EhCache 所有缓存对象的键和值都必须是可序列化的,也就是必须实现 java.io.Serializable 接口,这点在其它集群方式下也是需要遵守的。

5.1.1 RMI集群模式结构及原理

RMI 集群模式的结构如下图5.1所示:

                      图5.1

采用 RMI 集群模式时,集群中的每个节点都是对等关系,并不存在主节点或者从节点的概念,因此节点间必须有一个机制能够互相认识对方,必须知道其它节点的信息,包括主机地址、端口号等。EhCache 提供两种节点的发现方式:手工配置和自动发现。手工配置方式要求在每个节点中配置其它所有节点的连接信息,一旦集群中的节点发生变化时,需要对缓存进行重新配置。

由于RMI是Java 中内置支持的技术,因此使用 RMI 集群模式时,无需引入其它的Jar包,Ehcache 本身就带有支持 RMI 集群的功能。使用 RMI 集群模式需要在ehcache.xml配置文件中定义 cacheManagerPeerProviderFactory 节点。

5.1.2 RMI集群例子

我们可以按照以下步骤来进行来完成这个例子:

1)          按照第3章相同的方法新建一个java工程ehcache-test-b

我们工作空间工程结构如下图5.2所示:

                图5.2

注意:ehcache-test-b工程的测试类名为TestMainB,以方便后续在Eclipse的console里区分

2)          修改ehcache.xml配置文件;

   为了保存先前的成果,我们新建一份名为ehcache_cluster.xml的配置文件。

   ehcache_cluster.xml配置文件的内容为:

<?xmlversion="1.0"encoding="UTF-8"?>

 

<ehcachexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:noNamespaceSchemaLocation="ehcache.xsd"updateCheck="false"

    monitoring="autodetect"dynamicConfig="true">

    <diskStorepath="user.home"/>

 

    <!-- 指定除自身之外的网络群体中其他提供同步的主机列表,用“|”分开不同的主机 -->

    <cacheManagerPeerProviderFactory

       class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"

    properties="peerDiscovery=manual,rmiUrls=//127.0.0.1:60000/UserCache|//127.0.0.1:40000/UserCache"/>

 

    <!-- 配宿主主机配置监听程序,来发现其他主机发来的同步请求 -->

    <cacheManagerPeerListenerFactory

       class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"

       properties="port=40000,socketTimeoutMillis=120000"/>

 

    <!-- 默认缓存 -->

    <defaultCachemaxElementsInMemory="10000"eternal="false"

       timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="true"

       diskSpoolBufferSizeMB="30"maxElementsOnDisk="10000000"

       diskPersistent="false"diskExpiryThreadIntervalSeconds="120"

       memoryStoreEvictionPolicy="LRU">

    </defaultCache>

 

    <!-- 缓存 -->

    <cachename="UserCache"maxElementsInMemory="10000"eternal="false"

       timeToIdleSeconds="100000"timeToLiveSeconds="100000"overflowToDisk="false">

       <cacheEventListenerFactory

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

       <bootstrapCacheLoaderFactory

           class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"

           properties="bootstrapAsynchronously=false"/>

    </cache>

 

</ehcache>

    然后,将ehcache-test工程的ehcache_cluster.xml拷贝一份到ehcache-test-b工程对应目录下;修改ehcache-test-b工程中的ehcache_cluster.xml中的cacheManagerPeerProviderFactory配置项内容为:

    <!-- 配宿主主机配置监听程序,来发现其他主机发来的同步请求 -->

    <cacheManagerPeerListenerFactory

       class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"

       properties="port=60000,socketTimeoutMillis=120000"/>

修改完配置文件后的工程结构如下图5.3所示:

               图5.3

3)          编写java测试方法

在ehcache-test工程的TestMain.java文件中添加以下代码:

    @Test

    public void testF3() throws Exception {

       URLurl = TestMain.class.getClassLoader().getResource(

              "conf/ehcache_cluster.xml");

       CacheManagermanager = new CacheManager(url);

 

       Cachecache1 = manager.getCache("UserCache");

       Stringkey = "key1";

       Stringvalue = key.hashCode() + "";

 

       Elementelement1 = new Element(key, value);

       cache1.put(element1);

       System.out.println(cache1.get(key));

 

       manager.shutdown();

   }

在ehcache-test-b工程的TestMainB.java文件中添加以下代码:

    @Test

    public void testF3() throws Exception {

       URLurl = TestMainB.class.getClassLoader().getResource(

              "conf/ehcache_cluster.xml");

       CacheManagermanager = new CacheManager(url);

       Cachecache1 = manager.getCache("UserCache");

      

       while (true) {

           Stringkey = "key1";

           System.out.println("get value by aaa");

           Elementelement = cache1.get(key);

           if (element !=null) {

              System.out.println(element.getValue());

              break;

           }

           Thread.sleep(1000);

       }

       manager.shutdown();

   }

4)          运行测试程序;

   先运行ehcache-test-b工程的TestMainB.java文件中testF3()方法,再运行ehcache-test工程的TestMain.java文件中testF3()方法。在正常情况下,不久会,程序就可运行完成。

ehcache-test-b工程运行的结果如下图5.4所示:

                               图5.4

ehcache-test工程运行的结果如下图5.5所示:

                            图5.5

我们可以看到,正如我们所说,集群下的缓存数据同步实现了。

5.1.3 RMI集群配置文件说明

要实现RMI集群环境下缓存数据同步,我们只要修改好缓存配置文件就可以了。

配置文件片段1:

<!-- 指定除自身之外的网络群体中其他提供同步的主机列表,用“|”分开不同的主机 -->

    <cacheManagerPeerProviderFactory

       class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"

   properties="peerDiscovery=manual,rmiUrls=//127.0.0.1:60000/UserCache|//127.0.0.1:40000/UserCache"/>

此段配置定义了网络集群环境中其他提供数据同步的主机声明。Properties属性主要由两个属性,peerDiscovery和rmiUrls。其说明如下:

peerDiscovery= automatic:自动发现其他主机;

peerDiscovery= manual:指定其他主机列表。

当peerDiscovery= automatic时,我们还需要指定以下属性值:

multicastGroupAddress:组播地址;如230.0.0.1

multicastGroupPort:组播主机端口;如60000

timeToLive:组播传播范围;如32

当peerDiscovery= manual时,正如上面例子一样,我们只需要列出所有的其他主机列表,例如:

rmiUrls=//127.0.0.1:60000/UserCache|//127.0.0.1:40000/UserCache

为了配置方便,我们可以把本机也配置在主机列表中,如例子所示。

配置文件片段2:

    <!-- 配宿主主机配置监听程序,来发现其他主机发来的同步请求 -->

    <cacheManagerPeerListenerFactory

       class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"

       properties="port=40000,socketTimeoutMillis=120000"/>

正如注释描述的,此处申明本机的ip和端口号,以使得其他主机能发现本机。Properties可以配置的属性如下:

hostName:主机ip;默认为127.0.0.1

port:主机端口号;如60000

socketTimeoutMillis:socket超时时间设置;如120000

配置文件片段3:

    <!-- 缓存 -->

    <cachename="UserCache"maxElementsInMemory="10000"eternal="false"

       timeToIdleSeconds="100000"timeToLiveSeconds="100000"overflowToDisk="false">

       <cacheEventListenerFactory

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

   </cache>

需要同步数据的缓存中加入cacheEventListenerFactory配置。

5.2 集群模式中的其他特性说明

对于集群环境中使用ehcache实现数据同步的过程中,采用RMI方式的时候,数据只有被put、remove等操作时,才会将数据同步到其他主机中。因为这样,就可能会出现这样的问题:当一个节点中的服务器停机了,当重新启动该节点服务器时,服务器中的cache数据为空。我们希望,这个时候,该节点能迅速从其他各个节点中得到已经被缓存的数据。

针对这个问题,Ehcache的缓存配置中,有这样一个配置bootstrapCacheLoaderFactory。完整的配置如下:

    <cachename="UserCache"maxElementsInMemory="10000"eternal="false"

       timeToIdleSeconds="100000"timeToLiveSeconds="100000"overflowToDisk="false">

    <cacheEventListenerFactory

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

    <bootstrapCacheLoaderFactory

       class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"

       properties="bootstrapAsynchronously=false"/>

   </cache>

有兴趣的读者,可以将此配置拷贝到自己的测试工程配置文件中,编写java测试方法来模拟上述情况,并查看结果。

6     总结

在现在的IT应用中,有很多cache的产品或者框架,比如jbosscache、OScache、MemCache,当然还有Ehcache等等。其中用得最为广泛的,应该是Ehcache和MemCache。

Ehcache的特点前面已经有所描述,这里不再赘述。简单地说,在java的较小型的项目中,一般都采用Ehcache。

MemCache作为大型项目或者网站常采用的分布式缓存方案,在分布式集群方面有其独特之处。MemCache一般需要单独部署在一台服务器上,而Ehcache常常作为java应用系统的一个插件部分用于项目中。

Ehcache的功能很强大,更多地关于Ehcache的使用,请参照其官方使用手册。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值