精华内容
下载资源
问答
  • ehcache 中文
    千次阅读
    2020-09-25 11:40:13

    官网链接:https://www.ehcache.org/

    官网英文文档链接:https://www.ehcache.org/documentation/3.8/getting-started.html

    Maven 依赖:

        <dependency>
          <groupId>org.ehcache</groupId>
          <artifactId>ehcache</artifactId>
          <version>3.8.1</version>
        </dependency>  

    Ehcache 3 API 用法:

    CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() //1
        .withCache("preConfigured",
            CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))) //2
        .build(); //3
    cacheManager.init(); //4
    
    Cache<Long, String> preConfigured =
        cacheManager.getCache("preConfigured", Long.class, String.class); //5
    
    Cache<Long, String> myCache = cacheManager.createCache("myCache", //6
        CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)));
    
    myCache.put(1L, "da one!"); //7
    String value = myCache.get(1L); //8
    
    cacheManager.removeCache("preConfigured"); //9
    
    cacheManager.close(); //10
    1. 静态方法org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder返回一个新的org.ehcache.config.builders.CacheManagerBuilder实例。
    2. 用builder来定义一个别名为"preConfigured"的Cache。调用cacheManager.build()时会创建该cache。withCache()方法的第一个参数是cache别名,用来以后取缓存用。第二个参数用来配置Cache,我们用静态方法newCacheConfigurationBuilder()来创建默认的配置。
    3. 调用build会返回一个已经实例化但还没有初始化的CacheManager。
    4. 使用CacheManager前需要先初始化。有两种方法可以进行初始化:调用CacheManager.init()或者调用CacheManagerBuilder.build(boolean init)。
    5. 为了从CacheManager获得一个cache,我们需要传递alias, key type和value type。例如,在第二步中,传递alias="preConfigured",keyType=Long.class,valueType=String.class。如果type不匹配,CacheManager会抛出ClassCastException。这样可以保护Cache不被随机的type污染。
    6. 实例化并初始化的Cache可以通过CacheManager.getCache来获取。
    7. 新建的Cache现在可以用来存储元素了。第一个参数是key,第二个是value,key和value的type必须和CacheConfiguration中定义的一直。
    8. 调用cache.get(key)可以获得值。如果没有值则会返回null。
    9. 调用CacheManager.removeCache(String)可以删除Cache。CacheManager不仅会删除Cache的reference,同时会关闭Cache。
    10. CacheManager.close()会关闭所有的Cache实例。

    XML configuration配置文件

    你可以创建一个XML文件来配置CacheManager。

    <config
        xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
        xmlns='http://www.ehcache.org/v3'
        xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core.xsd">
    
      <cache alias="foo"> //1
        <key-type>java.lang.String</key-type> //2
        <value-type>java.lang.String</value-type> //2
        <resources>
          <heap unit="entries">20</heap> //3
          <offheap unit="MB">10</offheap> //4
        </resources>
      </cache>
    
      <cache-template name="myDefaults"> //5
        <key-type>java.lang.Long</key-type>
        <value-type>java.lang.String</value-type>
        <heap unit="entries">200</heap>
      </cache-template>
    
      <cache alias="bar" uses-template="myDefaults"> //6
        <key-type>java.lang.Number</key-type>
      </cache>
    
      <cache alias="simpleCache" uses-template="myDefaults" /> //7
    
    </config>
    1. 给Cache别名为foo。
    2. foo的key,value的type定义为String;如果没有特别定义,默认是java.lang.Object。
    3. foo最多在堆中有2000个entry。
    4. 最多500MB的堆外内存。
    5. <cache-template>可以让你创建一个abstract配置并以后extend它。
    6. 命名为bar的缓存用到了命名为myDefaults的<cache-template>并override它的key-type到java.lang.Number。
    7. 命名为simpleCache的缓存用myDefaults来作为它的缓存配置。

    为了解析一个XML配置,你可以用XmlConfiguration:

    URL myUrl = getClass().getResource("/my-config.xml"); //1
    Configuration xmlConfig = new XmlConfiguration(myUrl); //2
    CacheManager myCacheManager = CacheManagerBuilder.newCacheManager(xmlConfig); //3
    1. 添加XML路径。
    2. 实例化XMLConfiguration。
    3. 用静态方法org.ehcache.config.builders.CacheManagerBuilder.newCacheManager(org.ehcache.config.Configuration)创建CacheManager实例。

    集群方案下创建cache manager

    为了支持Terracotta集群方案,需要先启动start the Terracotta server。此外,为了创建集群方案的cache manager,亦需要提供集群服务的配置:

    CacheManagerBuilder<PersistentCacheManager> clusteredCacheManagerBuilder =
        CacheManagerBuilder.newCacheManagerBuilder() 
            .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")) 
                .autoCreate(c -> c)); 
    PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true); 
    
    cacheManager.close(); 
    1. 返回org.ehcache.config.builders.CacheManagerBuilder实例。
    2. 用静态方法ClusteringServiceConfigurationBuilder.cluster(URI)来连接对应URI的集群。例子中的URI指向identifier为my-application的集群(默认端口号9410);auto-create会在server中的集群不存在时创建。
    3. 返回一个完全初始化的cache manager。
    4. 集群没有时会自动创建。
    5. 关闭cache manager。

    Storage Tiers存储层级

    Ehcache可以在数据越来越大时,存储到相对较慢的层级中。

    因为快速的存储资源相对稀有,所以hottest的资源会存在这里。因此那些较少用到的data会被移动到较慢但存储容量更大的层级中。更频繁用到的数据会移动到更快的层级中。

    经典的3层级带硬盘存储的方案:

    PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder()
        .with(CacheManagerBuilder.persistence(new File(getStoragePath(), "myData"))) //1
        .withCache("threeTieredCache",
            CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
                ResourcePoolsBuilder.newResourcePoolsBuilder()
                    .heap(10, EntryUnit.ENTRIES) //2
                    .offheap(1, MemoryUnit.MB) //3
                    .disk(20, MemoryUnit.MB, true) //4 
                )
        ).build(true);
    
    Cache<Long, String> threeTieredCache = persistentCacheManager.getCache("threeTieredCache", Long.class, String.class);
    threeTieredCache.put(1L, "stillAvailableAfterRestart"); //5
    
    persistentCacheManager.close();
    1. 如果你希望使用硬盘存储,你要提供一个path给CacheManagerBuilder.persistence()方法。
    2. 给堆定义一个资源池。这是一个较快但是较小的池。
    3. 给堆外内存定义一个资源池。这是一个较快单大一点的池。
    4. 给硬盘定义一个持久化的资源池。
    5. 所有存在cache中的值都可以在JVM重启后获得。

    Data freshness缓存失效

    缓存失效通过Expiry控制。下面这个例子展示了如果控制缓存失效:

    CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
            ResourcePoolsBuilder.heap(100)) //1
        .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(20))) //2
        .build();
    1. Expiry在定义cache confuguration的时候配置的。
    2. 通过Duration配置time-to-live失效时间。

     

    更多相关内容
  • 标签:ehcache、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。
  • Ehcache中文指南和实例教程
  • ehcache官方文档

    2018-09-21 16:59:24
    ehcache官方文档:包含说明、操作指南、配置指南、spring集成等
  • Ehcache中文指南和实例教程.doc

    热门讨论 2012-04-01 09:39:52
    Ehcache中文指南和实例教程 好东西来的, 入门必备
  • 标签:ehcache中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。
  • 标签:sf、ehcache、web、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用...
  • 标签:sf、ehcache、core、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心...
  • 标签:apache、shiro、ehcache中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请...
  • 标签:apache、shiro、ehcache中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请...
  • 标签:apache、shiro、ehcache中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请...
  • 包含翻译后的API文档:ehcache-2.10.0-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId:net.sf.ehcache,artifactId:ehcache,version:2.10.0 使用方法:解压翻译后的API文档,用浏览器打开“index....
  • Ehcache使用手册

    2013-01-18 10:06:32
    Ehcache API,页面缓存,分布式缓存。
  • 包含翻译后的API文档:ehcache-2.10.0-javadoc-API文档-中文(简体)-英语-对照版.zip 对应Maven信息:groupId:net.sf.ehcache,artifactId:ehcache,version:2.10.0 使用方法:解压翻译后的API文档,用浏览器打开...
  • 包含翻译后的API文档:ehcache-core-2.6.11-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:net.sf.ehcache:ehcache-core:2.6.11; 标签:sf、ehcache、core、中英对照文档、jar包、java; 使用方法:...
  • 包含翻译后的API文档:ehcache-3.9.9-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.ehcache:ehcache:3.9.9; 标签:ehcache、jar包、java、中英对照文档; 使用方法:解压翻译后的API文档,用...
  • ehcache官方文档(译)

    千次阅读 2018-11-22 16:41:36
    Assuming that you have the clustered Ehcache kit available locally, start with extracting the  ehcache-clustered  kit. Change to your extracted directory and then execute the  start-tc-server  ...

    Introduction

    Distributed caching allows you to harness additional benefits of horizontal scale-out, without losing on low latency offered by local on-heap tiers.

    集群可以让你获得水平拓展的好处,同时又不失去本地查找低延迟的能力。

    To enable clustering with Terracotta, you will have to deploy a Terracotta server configured with clustered cache storage. For convenience Ehcache 3.1 introduced a downloadable kit that contains the Terracotta Server and also the required client libraries.

    使用Terracotta部署集群你需要部署一个可配置的Terracotta服务用来存储集群信息,为了方便 Ehcache 3.1已经引入过一个可以下载的包含Terracotta 服务和必要依赖的客户端。

    You will then need to configure a cache manager to have clustering capabilities such that the caches it manages can utilize the clustered storage. Finally, any caches which should be distributed should be configured with a clustered storage tier.

    为了拥有集群的性能你需要配置一个缓存管理 器,它管理的缓存可以使用集群存储,任何需要分布式的缓存都需要配置在一个集群存储中

    Clustering Concepts

    In this section we discuss some Terracotta clustering terms and concepts that you need to understand before creating cache managers and caches with clustering support.

    在建立缓存管理器和缓存集群之前我们要讨论Terracotta集群的地位和概念

    Server off-heap resource 服务器的堆外资源

    Server off-heap resources are storage resources defined at the server. Caches can reserve a storage area for their cluster tiers within these server off-heap resources.

    服务器堆外资源是在服务器上定义的存储资源,缓存可以在这些服务器堆外资源中为它们的集群层保留一个存储区域。

    Cluster Tier Manager 集群管理器

    The Ehcache Cluster Tier Manager is the server-side component that gives clustering capabilities to a cache manager. Cache managers connect to it to get access to the server’s storage resources so that the clustered tiers of caches defined in them can consume those resources. An Ehcache cluster tier manager at the server side is identified by a unique identifier. Using the unique identifier of any given cluster tier manager, multiple cache managers can connect to the same cluster tier manager in order to share cache data. The cluster tier manager is also responsible for managing the storage of the cluster tier of caches, with the following different options.

    Ehcache集群层管理器是向缓存管理器提供集群功能的服务器端组件。缓存管理器连接到它,以访问服务器的存储资源,以便其中定义的缓存集群层可以使用这些资源。服务器端的Ehcache集群层管理器由唯一标识符标识。使用任何给定集群层管理器的唯一标识符,多个缓存管理器可以连接到同一个集群层管理器,以便共享缓存数据。集群层管理器还负责管理缓存的集群层的存储,具有以下不同的配置项。

    Dedicated pool 专用池

    Dedicated pools are a fixed-amount of storage pools allocated to the cluster tiers of caches. A dedicated amount of storage is allocated directly from server off-heap resources to these pools. And this storage space is used exclusively by a given cluster tier.

    专用池是分配给缓存集群层的固定数量的存储池。从服务器堆外资源直接给这些池分配专用的存储空间。这个存储空间仅由给定的集群层使用。

    Shared pool 共享池

    Shared pools are also fixed-amount storage pools, but can be shared by the cluster tiers of multiple caches. As in the case of dedicated pools, shared pools are also carved out from server off-heap resources. The storage available in these shared pools is strictly shared. In other words, no cluster tier can ask for a fixed-amount of storage from a shared pool.

    共享池也是固定数量的存储池,但是可以由多个缓存的集群层共享。与专用池的情况一样,共享池也是从服务器堆外资源中分割出来的。这个共享池是被严格定义为共享的,换句话说,没有集群层可以从共享池中申请到一块固定大小的空间。

    Sharing of storage via shared pools does not mean that the data is shared. That is, if two caches are using a shared pool as their clustered tier, the data of each cache is still isolated but the underlying storage is shared. Consequently, when resource capacity is reached and triggers eviction, the evicted mapping can come from any of the cluster tiers sharing the pool.

    通过共享池共享存储并不意味着数据是共享的。也就是说,如果两个缓存使用共享池作为它们的集群层,那么每个缓存的数据仍然是独立的,但是底层存储是共享的。当资源达到回收条件,回收的映射可以来自集群层的任何一块共享池。

    Here is a pictorial representation of the concepts explained above:

    以下是上述概念的图示:

    Starting the Terracotta Server

    You can start the Terracotta Server with the following configuration. It contains the bare minimum configuration required for the samples in the rest of the document to work.

    您可以使用以下配置启动Terracotta服务器。它包含文档示例所需的最低配置。

    <?xml version="1.0" encoding="UTF-8"?>

    <tc-config xmlns="http://www.terracotta.org/config"

               xmlns:ohr="http://www.terracotta.org/config/offheap-resource">

      <plugins>

        <config>

          <ohr:offheap-resources>

            <ohr:resource name="primary-server-resource" unit="MB">128</ohr:resource>  

            <ohr:resource name="secondary-server-resource" unit="MB">96</ohr:resource> 

          </ohr:offheap-resources>

        </config>

      </plugins>

    </tc-config>

    The above configuration defines two named server off-heap resources:

    上面的配置定义了两个命名的服务器堆外资源

     

    An off-heap resource of 128 MB size named primary-server-resource.

     

    Another off-heap resource named secondary-server-resource with 96 MB capacity.

    The rest of the document explains in detail how you can configure cache managers and caches to consume the server’s off-heap resources.

    本文的其余部分将详细说明如何配置缓存管理器和缓存,以使用服务器的堆外资源

    Assuming that you have the clustered Ehcache kit available locally, start with extracting the ehcache-clustered kit. Change to your extracted directory and then execute the start-tc-server script as below to start the Terracotta server with the above configuration:

    假设您有本地可用的集群Ehcache工具包,那么从解压的Ehcache集群工具包启动。切换到提取的目录,然后执行start-tc-server脚本(如下所示),使用上述配置启动Terracotta服务器

    On Windows:windows下启动

    cd <path/to/terracotta/kit>/server/bin

    start-tc-server.bat -f <path/to/server/config>/tc-config.xml

    On Unix/Mac:Mac启动

    cd <path/to/terracotta/kit>/server/bin

    ./start-tc-server.sh -f <path/to/server/config>/tc-config.xml

     

    You will need to have JAVA_HOME point to a Java 8 installation while starting the Terracotta server.

    Check for the below INFO log to confirm if the server started successfully, Terracotta Server instance has started up as ACTIVE node on 0:0:0:0:0:0:0:0:9410 successfully, and is now ready for work.

    检查是否有以下输出,确定是否启动成功

    Terracotta Server instance has started up as ACTIVE node on 0:0:0:0:0:0:0:0:9410 successfully, and is now ready for work.

     

    Creating a Cache Manager with Clustering Capabilities

    创建具有集群功能的缓存管理器

    After starting the Terracotta server, as described in the previous section, you can now proceed to create the cache manager. For creating the cache manager with clustering support you will need to provide the clustering service configuration. Here is a code sample that shows how to configure a cache manager with clustering service.

    在启动Terracotta服务器(如前一节所述)之后,现在可以继续创建缓存管理器。要创建具有集群支持的缓存管理器,您需要提供集群服务配置。下面的代码示例演示如何使用集群服务配置缓存管理器。

    CacheManagerBuilder<PersistentCacheManager> clusteredCacheManagerBuilder =

        CacheManagerBuilder.newCacheManagerBuilder()

            .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application"))

                .autoCreate());

    PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true);

     

    cacheManager.close();

     

    Returns the org.ehcache.config.builders.CacheManagerBuilder instance.

    返回org.ehcache.config.builders.CacheManagerBuilder实例

     

    Use the ClusteringServiceConfigurationBuilder static method .cluster(URI) for

    connecting the cache manager to the clustered storage at the URI specified that

     returns the clustering service configuration builder instance.

     Sample URI 

    Provided in the example is pointing to the clustered storage instance named

    "my-application" on the Terracotta server (assuming the server is running on

    localhost and port 9410).

    使用ClusteringServiceConfigurationBuilder 静态方法.cluster(URI)用来把缓存管理器连接

    到uri指定的集群存储,返回集群服务可配置建造者实例。

    简单说这个例子提供的URI指定到集群存储实例在Terracotta 服务叫做"my-application"(

    假设这个服务运行在你本机的9410端口)

     

    Auto-create the clustered storage if it doesn’t already exist.

    如果当前不存在自动创建集群存储。

     

    Returns a fully initialized cache manager that can be used to create clustered

    caches.

    返回一个可以用来创建集群缓存的全部序列化的缓存管理器

     

    Close the cache manager.

    关闭缓存管理器

    Cache Manager Configuration and Usage of Server Side Resources

    缓存管理器配置和服务器端资源的使用

    This code sample demonstrates the usage of the concepts explained in the previous section in configuring a cache manager and clustered caches by using a broader clustering service configuration:

    这个代码示例演示了使用更广泛的集群服务配置来配置缓存管理器和集群缓存时,在前一节中解释的概念的用法:

    CacheManagerBuilder<PersistentCacheManager> clusteredCacheManagerBuilder =

        CacheManagerBuilder.newCacheManagerBuilder()

            .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")).autoCreate()

                .defaultServerResource("primary-server-resource")

                .resourcePool("resource-pool-a", 28, MemoryUnit.MB, "secondary-server-resource")

                .resourcePool("resource-pool-b", 32, MemoryUnit.MB))

            .withCache("clustered-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,

                ResourcePoolsBuilder.newResourcePoolsBuilder()

                    .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 32, MemoryUnit.MB))))

            .withCache("shared-cache-1", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,

                ResourcePoolsBuilder.newResourcePoolsBuilder()

                    .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool-a"))))

            .withCache("shared-cache-2", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,

                ResourcePoolsBuilder.newResourcePoolsBuilder()

                    .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool-a"))));

    PersistentCacheManager cacheManager = clusteredCacheManagerBuilder.build(true);

     

    cacheManager.close();

     

    defaultServerResource(String) on ClusteringServiceConfigurationBuilder instance

    sets the default server off-heap resource for the cache manager. From the example,

    cache manager sets its default server off-heap resource to primary-server-resource

    in the server.

    ClusteringServiceConfigurationBuilder实例的defaultServerResource(String) 方法为

    缓存管理器设置了默认的堆外资源。例如缓存管理器为服务中的primary-server-resource

    设置了默认的堆外资源。

     

    Adds a resource pool for the cache manager with the specified name (resource-pool-a)

    and size (28MB) consumed out of the named server off-heap resource

     secondary-server-resource. A resource pool at the cache manager level

     maps directly to a shared pool at the server side.

    从被命名的堆外内存为缓存管理器指定名称 (resource-pool-a)和大小(28MB)的资源

    secondary-server-resource。缓存管理器资源池映射到服务器端的共享池中。

     

    Adds another resource pool for the cache manager with the specified name

     (resource-pool-b) and size (32MB). Since the server resource identifier is not

     explicitly passed, this resource pool will be consumed out of default server

     resource provided in Step 3. This demonstrates that a cache manager with clustering

    support can have multiple resource pools created out of several

     server off-heap resources.

    为缓存管理器添加另一个资源池名字叫做 (resource-pool-b)大小为32M.因为服务资源没有显示

    指定,资源池将从默认的服务使用第三步提供。这说明集群的缓存管理器

    支持可以在多个资源池中创建多个堆外资源池

     

    Provide the cache configuration to be created.

    一个缓存配置被创建

     

    ClusteredResourcePoolBuilder.clusteredDedicated(String, long, MemoryUnit) 

    allocates a dedicated pool of storage to the cache from the specified

    server off-heap resource. In this example, a dedicated pool of 32MB is

    allocated for clustered-cache from primary-server-resource.

     

    ClusteredResourcePoolBuilder.clusteredDedicated(String, long, MemoryUnit) 

    从指定堆外服务资源分配一个专用的资源池用来缓存数据。这个例子中,

    primary-server-resource.为集群缓存分配了32mb专用内存。

     

    ClusteredResourcePoolBuilder.clusteredShared(String), passing the name of

    the resource pool specifies that shared-cache-1 shares the storage

    resources with other caches using the same resource pool (resource-pool-a).

    省略掉资源池名称shared-cache-1 与其他缓存使用相同的资源池 (resource-pool-a)

    共享存储资源

     

    Configures another cache (shared-cache-2) that shares the resource pool

    (resource-pool-a) with shared-cache-1.

    配置另一个缓存 (shared-cache-2) shared-cache-1.共享资源池(resource-pool-a)

     

    Creates fully initialized cache manager with the clustered caches.

    使用集群缓存创建完全初始化的缓存管理器。

     

     

    When a cache is allocated a block of memory from a shared pool, it is retained forever and would never get reallocated to another cache sharing the pool.

    当缓存在共享池中分配了一个块,它将永远的被共享。

    Ehcache Cluster Tier Manager Lifecycle

    Ehcache集群层管理器生命周期

    When configuring a cache manager to connect to a cluster tier manager there are three possible connection modes:

    在配置缓存管理器以连接到集群层管理器时,有三种可能的连接模式

    CacheManagerBuilder<PersistentCacheManager> autoCreate = CacheManagerBuilder.newCacheManagerBuilder()

            .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application"))

                .autoCreate()

                .resourcePool("resource-pool", 32, MemoryUnit.MB, "primary-server-resource"))

            .withCache("clustered-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,

                ResourcePoolsBuilder.newResourcePoolsBuilder()

                    .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool"))));

     

    CacheManagerBuilder<PersistentCacheManager> expecting = CacheManagerBuilder.newCacheManagerBuilder()

            .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application"))

                .expecting()

                .resourcePool("resource-pool", 32, MemoryUnit.MB, "primary-server-resource"))

            .withCache("clustered-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,

                ResourcePoolsBuilder.newResourcePoolsBuilder()

                    .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool"))));

     

    CacheManagerBuilder<PersistentCacheManager> configless = CacheManagerBuilder.newCacheManagerBuilder()

            .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application")))

                

            .withCache("clustered-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,

                ResourcePoolsBuilder.newResourcePoolsBuilder()

                    .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool"))));

     

    在自动创建模式中如果不存在集群层管理器则按照提供的配置创建一个。如果存在并且它的

    配置与提供的匹配,则建立一个连接,如果提供的配置与缓存管理器不匹配则初始化失败。

    In auto-create mode if no cluster tier manager exists then one is created with the

    supplied configuration. If it exists and its configuration matches the supplied

    configuration then a connection is established. If the supplied configuration does

     not match then the cache manager will fail to initialize.

     

    在期望模式中如果一个集群层管理器存在,并且它的配置与提供的配置匹配则建立连接。

    如果提供的配置不匹配,或者集群管理器不存在,则初始化失败。

    In expected mode if a cluster tier manager exists and its configuration matches the

     supplied configuration then a connection is established. If the supplied

    configuration does not match or the cluster tier manager does not exist then the

    cache manager will fail to initialize.

     

    在少配置模式中如果集群层管理器存在则建立一个连接

    In config-less mode if a cluster tier manager exists then a connection is

    established without regard to its configuration. If it does not exist then the

    cache manager will fail to initialize.

    Configuring a Clustered Cache

    配置缓存集群

    Clustered Storage Tier

    集群存储层

    CacheConfiguration<Long, String> config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,

        ResourcePoolsBuilder.newResourcePoolsBuilder()

            .heap(2, MemoryUnit.MB)

            .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB)))

        .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))

        .build();

     

    Cache<Long, String> cache = cacheManager.createCache("clustered-cache-tiered", config);

    cache.put(42L, "All you need to know!");

     

    Configuring the heap tier for cache.

    为缓存配置堆层

     

    Configuring the cluster tier of dedicated size from server off-heap resource using 

    ClusteredResourcePoolBuilder.

    使用ClusteredResourcePoolBuilder为集群层配置专用的堆外内存

    The equivalent XML configuration is as follows:

    使用一下xml配置效果相同

    <cache alias="clustered-cache-tiered">

      <resources>

        <heap unit="MB">10</heap>

        <tc:clustered-dedicated unit="MB">50</tc:clustered-dedicated>

      </resources>

      <tc:clustered-store consistency="strong"/>

    </cache>

     

    Specify the heap tier for cache.

    配置堆内存

     

    Specify the cluster tier for cache through a custom service configuration from

     the clustered namespace.

    配置堆外内存

    Specifying consistency level

    一致性级别

    Ehcache offers two levels of consistency:

    Ehcache提供两个级别的一致性:

    Eventual最终一致性

    This consistency level indicates that the visibility of a write operation is not guaranteed when the operation returns. Other clients may still see a stale value for the given key. However this consistency level guarantees that for a mapping (K, V1) updated to (K, V2), once a client sees (K, V2) it will never see (K, V1) again.

    这个一致性级别无法保证一个写入,另一个客户端使用相同的key查询马上就能看到写入的结果。但是这个级别可以保证从(K, V1)更新到(K, V2)一旦查到(K, V2)就再也不会查到(K, V1) (言外之意不会回滚)

    Strong 强一致

    This consistency level provides strong visibility guarantees ensuring that when a write operation returns other clients will be able to observe it immediately. This comes with a latency penalty on the write operation required to give this guarantee.

    一旦一个连接写入成功,所有的连接都能同步感知到变化。这个是需要写入端保证的。

    CacheConfiguration<Long, String> config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,

            ResourcePoolsBuilder.newResourcePoolsBuilder()

                    .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 2, MemoryUnit.MB)))

        .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))

        .build();

     

    Cache<Long, String> cache = cacheManager.createCache("clustered-cache", config);

    cache.put(42L, "All you need to know!");

     

    Specify the consistency level through the use of additional service configuration,

     using strong consistency here.

    通过给服务添加额外配置条件指定一致性等级,这里使用强一致性

     

    With the consistency used above, this put operation will return only when

    all other clients have had the corresponding mapping invalidated.

    使用上边的一致性,这个放入操作会导致其他客户的缓存映射失效。

    The equivalent XML configuration is as follows:

    <cache alias="clustered-cache">

      <resources>

        <tc:clustered-dedicated unit="MB">50</tc:clustered-dedicated>

      </resources>

      <tc:clustered-store consistency="strong"/>

    </cache>

     

    Specify the consistency level through a custom service configuration from the

     clustered namespace.

    从集群命名空间通过客户端服务配置指定一致性等级

    Clustered Cache Expiry

    缓存过期

    Expiry in clustered caches work with an exception that Expiry#getExpiryForAccess is handled on a best effort basis for cluster tiers. It may not be as accurate as in the case of local tiers.

    Clustered Unspecified Inheritance

    We have included an option which allows a cache to be created inside the cache manager without having to explicitly define its cluster tier resource pool allocation. In order to use this feature the cluster tier must already have been created with either a shared or dedicated resource pool.

    有一个选项允许缓存在缓存管理器中创建无需显式定义其集群层资源池分配。

    为了使用这一特性,集群层必须是在共享区或者是专区去创建。

    In this case the definition of the cluster resource is done simply with a clustered() resource pool. This effectively means unspecified and indicates you expect it to exist already. It will then inherit the clustered resource pool as it was configured when creating the cluster tier.

     

    This option provides many benefits. The main benefit is it simplifies clustered configuration by allowing clustered resource pool configuration to be handled by one client, then all subsequent clients can inherit this configuration. In addition, it also reduces clustered pool allocation configuration errors. More importantly, sizing calculations only need to be done by one person and updated in one location. Thus any programmer can use the cache without having to worry about using matching resource pool allocations.

    The example code below shows how this can be implemented.

    CacheManagerBuilder<PersistentCacheManager> cacheManagerBuilderAutoCreate = CacheManagerBuilder.newCacheManagerBuilder()

            .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application"))

                .autoCreate() 

                .resourcePool("resource-pool", 32, MemoryUnit.MB, "primary-server-resource"));

     

    PersistentCacheManager cacheManager1 = cacheManagerBuilderAutoCreate.build(false);

    cacheManager1.init();

     

    CacheConfiguration<Long, String> cacheConfigDedicated = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,

    ResourcePoolsBuilder.newResourcePoolsBuilder()

        .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 8, MemoryUnit.MB))) 

    .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))

    .build();

     

    Cache<Long, String> cacheDedicated = cacheManager1.createCache("my-dedicated-cache", cacheConfigDedicated); 

     

    CacheManagerBuilder<PersistentCacheManager> cacheManagerBuilderExpecting = CacheManagerBuilder.newCacheManagerBuilder()

            .with(ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost/my-application"))

                .expecting() 

                .resourcePool("resource-pool", 32, MemoryUnit.MB, "primary-server-resource"));

     

    PersistentCacheManager cacheManager2 = cacheManagerBuilderExpecting.build(false);

    cacheManager2.init();

     

    CacheConfiguration<Long, String> cacheConfigUnspecified = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,

    ResourcePoolsBuilder.newResourcePoolsBuilder()

        .with(ClusteredResourcePoolBuilder.clustered())) 

    .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))

    .build();

     

    Cache<Long, String> cacheUnspecified = cacheManager2.createCache("my-dedicated-cache", cacheConfigUnspecified);

     

    Configure the first cache manager with auto create

     

    Build a cache configuration for a clustered dedicated resource pool

     

    Create cache my-dedicated-cache using the cache configuration

     

    Configure the second cache manager as expecting (auto create off)

     

    Build a cache configuration for a clustered unspecified resource pool,

    which will use the previously configured clustered dedicated resource pool.

     

    Create cache with the same name my-dedicated-cache and use the clustered

     unspecified cache configuration

    Z

     

     

    CacheManagerBuilder缓存管理器建造者,通过with()方法,可以指定链接到那个集群(terracotta),并划分资源池,

                                                                    通过withcache()方法可以创建chache,并指定大小和区域,以及一致性等(也可使用cacheManager.createCache(方法创建))

    创建完成可以使用cacheManager.getCache("clustered-cache-tiered", Long.class, String.class);获取缓存操作对象。

    也可以新指定一个配置通过chacheManager新创建个对象:

                                CacheConfiguration<Long, String> config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,

                    ResourcePoolsBuilder.newResourcePoolsBuilder()

                            .heap(2, MemoryUnit.MB)//堆内两兆堆外8兆

                            .with(ClusteredResourcePoolBuilder.clusteredDedicated("default-resource", 8, MemoryUnit.MB)))

                    .add(ClusteredStoreConfigurationBuilder.withConsistency(Consistency.STRONG))

                    .build();

     

            Cache<Long, String> cache = cacheManager.createCache("clustered-cache-tiered", config);

    展开全文
  • EHCache技术文档-下载地址 欢迎关注公众号:

     

    EHCache技术文档-下载地址

    欢迎关注公众号:

    展开全文
  • mybatis ehcache 整合中文文档 mybatis ehcache 整合中文文档 mybatis ehcache 整合中文文档
  • 缓存的名字是ehcache。。。老是记得是encache....     官方PDF文档:http://www.ehcache.org/documentation/ehcache-2.5.x-documentation.pdf   0.需要的jar包:   1.首先要了解缓存清除策略,官方文档给...

      缓存的名字是ehcache。。。老是记得是encache....  

     

      官方PDF文档:http://www.ehcache.org/documentation/ehcache-2.5.x-documentation.pdf

     

    0.需要的jar包:

     

    1.首先要了解缓存清除策略,官方文档给出的有

      超过缓存指定的数量的时候按指定策略清除缓存的数据。参考:MemoryStoreEvictionPolicy类:

    LRU - least recently used(最近最少使用)
    LFU - least frequently used(最不经常使用)
    FIFO - first in first out, the oldest element by creation time(清除最早缓存的数据,不关心是否经常使用)
    CLOCK---FIFO - first in first out, the oldest element by creation time.(与FIFO一样)

     

     

    2.一个简单的使用

    1.使用缓存

    配置文件:

     <ehcache updateCheck="false" dynamicConfig="false">  
        <diskStore path="java.io.tmpdir"/>  
        
        <defaultCache  
            maxElementsInMemory="1000"  
            eternal="false"  
            overflowToDisk="true"  
            timeToIdleSeconds="120"  
            timeToLiveSeconds="120"  
            diskPersistent="false"  
            diskExpiryThreadIntervalSeconds="120"  
            memoryStoreEvictionPolicy="LRU"
        />      
         
        <cache name="cache_test" 
            maxElementsInMemory="2"  
            eternal="false"  
            timeToIdleSeconds="60"  
            timeToLiveSeconds="60"  
            maxElementsOnDisk="2"
            overflowToDisk="true"
            diskPersistent="false" 
            memoryStoreEvictionPolicy="FIFO"  
       />   
    </ehcache> 

     

     

    各配置参数的含义:
      maxElementsInMemory:缓存中允许创建的最大对象数

      maxElementsOnDisk:磁盘中允许的最多对象数
      eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。
      timeToIdleSeconds:缓存数据的钝化时间,也就是在一个元素消亡之前,两次访问时间的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0 就意味着元素可以停顿无穷长的时间。
      timeToLiveSeconds:缓存数据的生存时间,也就是一个元素从构建到消亡的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。
      overflowToDisk:内存不足时,是否启用磁盘缓存。

      diskPersistent 是否持久化磁盘缓存,当这个属性的值为true时,系统在初始化时会在磁盘中查找文件名为cache名称,后缀名为data的文件。指重启jvm后,数据是否有效。默认为false。

      memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。


      如果应用需要配置多个不同命名并采用不同参数的Cache,可以相应修改配置文件,增加需要的Cache配置即可。

     

    两个时间的详细解释:

      timeToLiveSeconds -->当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清除;即缓存自创建日期起能够存活的最长时间,单位为秒(s)

      timeToIdleSeconds -->  当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清空;即缓存被创建后,最后一次访问时间到缓存失效之时,两者之间的间隔,单位为秒(s)

      timeToLiveSeconds必须大于timeToIdleSeconds才有意义。

     

    测试代码:

    package encache;
    
    import java.util.Date;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import net.sf.ehcache.Cache;
    import net.sf.ehcache.CacheManager;
    import net.sf.ehcache.Element;
    
    public class FirstCache {
        private static final Logger log = LoggerFactory.getLogger(FirstCache.class.getName());
    
        // 1.创建CacheManager
    //    CacheManager cacheManager = CacheManager.create("E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml");// 也可以通过URL制定
        //一般用下面这种方式创建Cachemanager
    //    CacheManager cacheManager = CacheManager.create();//默认读取classpath目录下面的ehcache.xml
         CacheManager cacheManager = new  CacheManager();//默认读取classpath目录下面的ehcache.xml
    
        public FirstCache() {
            // 2.创建Cache
            Cache cache = cacheManager.getCache("cache_test");
            // 3.存取元素
            cache.put(new Element("firstCache", "第一个缓存元素"));
    
            // 4.获取元素
            Element element = cache.get("firstCache");
            log.info("获取的缓存元素是:{}", element);
            long creationTime = element.getCreationTime();
            long expirationTime = element.getExpirationTime();
            log.info("creationTime: {}", new Date(creationTime));
            log.info("expirationTime: {}", new Date(expirationTime));
    
            int diskStoreSize = cache.getDiskStoreSize();
            int cacheSize = cache.getKeys().size();
            log.info("diskStoreSize:{}", diskStoreSize);
            log.info("cacheSize: {}", cacheSize);
        }
    
        public static void main(String[] args) throws Exception {
            new FirstCache();
        }
    }

     

     

     结果:(注意存活时间是60s,注意标红的信息)

    2018-09-09 14:45:57 [net.sf.ehcache.CacheManager]-[DEBUG] Configuring ehcache from classpath.
    2018-09-09 14:45:57 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from ehcache.xml found in the classpath: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
    2018-09-09 14:45:57 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from URL: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
    2018-09-09 14:45:57 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from InputStream
    2018-09-09 14:45:58 [net.sf.ehcache.config.DiskStoreConfiguration]-[DEBUG] Disk Store Path: C:\Users\liqiang\AppData\Local\Temp\
    2018-09-09 14:45:58 [net.sf.ehcache.util.PropertyUtil]-[DEBUG] propertiesString is null.
    2018-09-09 14:45:58 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheManagerEventListenerFactory class specified. Skipping...
    2018-09-09 14:45:59 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
    2018-09-09 14:45:59 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
    2018-09-09 14:45:59 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
    2018-09-09 14:45:59 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
    2018-09-09 14:45:59 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
    2018-09-09 14:45:59 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
    2018-09-09 14:45:59 [net.sf.ehcache.store.MemoryStore]-[DEBUG] Initialized net.sf.ehcache.store.MemoryStore for cache_test
    2018-09-09 14:45:59 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.data
    2018-09-09 14:45:59 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.index
    2018-09-09 14:45:59 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Matching data file missing (or empty) for index file. Deleting index file C:\Users\liqiang\AppData\Local\Temp\cache_test.index
    2018-09-09 14:45:59 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.index
    2018-09-09 14:45:59 [net.sf.ehcache.Cache]-[DEBUG] Initialised cache: cache_test
    2018-09-09 14:45:59 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured. Skipping for 'cache_test'.
    2018-09-09 14:45:59 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured for defaultCache. Skipping for 'cache_test'.
    2018-09-09 14:45:59 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
    2018-09-09 14:45:59 [encache.FirstCache]-[INFO] 获取的缓存元素是:[ key = firstCache, value=第一个缓存元素, version=1, hitCount=1, CreationTime = 1536475559759, LastAccessTime = 1536475559799 ]
    2018-09-09 14:45:59 [encache.FirstCache]-[INFO] creationTime: Sun Sep 09 14:45:59 CST 2018
    2018-09-09 14:45:59 [encache.FirstCache]-[INFO] expirationTime: Sun Sep 09 14:46:59 CST 2018
    2018-09-09 14:45:59 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
    2018-09-09 14:45:59 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
    2018-09-09 14:45:59 [encache.FirstCache]-[INFO] diskStoreSize:0
    2018-09-09 14:45:59 [encache.FirstCache]-[INFO] cacheSize: 1

     

    并且在:C:\Users\liqiang\AppData\Local\Temp文件夹下面生成一个cache_test.data的文件。

     

     

    删除缓存只需要采用如下方法:

            // 4.删除一个元素
            cache.remove("key");

     

     

     

    2.获取缓存配置

    package encache;
    
    import java.util.Date;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import net.sf.ehcache.Cache;
    import net.sf.ehcache.CacheManager;
    import net.sf.ehcache.Element;
    import net.sf.ehcache.config.CacheConfiguration;
    import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
    
    public class FirstCache {
        private static final Logger log = LoggerFactory.getLogger(FirstCache.class.getName());
    
        // 1.创建CacheManager
        CacheManager cacheManager = new CacheManager();// 默认读取classpath目录下面的ehcache.xml
    
        public FirstCache() {
            // 2.创建Cache
            Cache cache = cacheManager.getCache("cache_test");
            CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
            // 2.1获取满了之后的清除策略
            MemoryStoreEvictionPolicy policy = cacheConfiguration.getMemoryStoreEvictionPolicy();
            log.info("{}", cacheConfiguration.getDiskStorePath());
            log.info("{}", cacheConfiguration.getTimeToIdleSeconds());
            log.info("{}", cacheConfiguration.getTimeToLiveSeconds());
            log.info("{}", cacheConfiguration.getMaxElementsInMemory());
            log.info("{}", cacheConfiguration.getMaxElementsOnDisk());
            log.info("{}", cacheConfiguration.getName());
            log.info("{}", policy.toString());
        }
    
        public static void main(String[] args) throws Exception {
            new FirstCache();
        }
    }

     

    结果:

    2018-09-09 15:08:14 [encache.FirstCache]-[INFO] null
    2018-09-09 15:08:14 [encache.FirstCache]-[INFO] 60
    2018-09-09 15:08:14 [encache.FirstCache]-[INFO] 60
    2018-09-09 15:08:14 [encache.FirstCache]-[INFO] 2
    2018-09-09 15:08:14 [encache.FirstCache]-[INFO] 2
    2018-09-09 15:08:14 [encache.FirstCache]-[INFO] cache_test
    2018-09-09 15:08:14 [encache.FirstCache]-[INFO] FIFO

     

    3.动态的修改缓存的配置:

    代码:

            cacheConfiguration.setDiskStorePath(System.getProperty("java.io.tmpdir"));
            cacheConfiguration.setTimeToIdleSeconds(200);
            cacheConfiguration.setTimeToLiveSeconds(200);
            cacheConfiguration.setMaxElementsInMemory(4);
            cacheConfiguration.setMaxElementsOnDisk(4);
            cacheConfiguration.setName("cache_test_update");
            cacheConfiguration.setMemoryStoreEvictionPolicy("CLOCK");

     

    直接修改会报错:

    Exception in thread "main" net.sf.ehcache.CacheException: Dynamic configuration changes are disabled for this cache
    at net.sf.ehcache.config.CacheConfiguration.checkDynamicChange(CacheConfiguration.java:2711)
    at net.sf.ehcache.config.CacheConfiguration.setDiskStorePath(CacheConfiguration.java:948)
    at encache.FirstCache.<init>(FirstCache.java:35)
    at encache.FirstCache.main(FirstCache.java:53)

     

    官方解释:原因是上面encache.xml阻止了动态修改cache配置

    Dynamic cache configurations can also be frozen to prevent future changes:
      Cache cache = manager.getCache("sampleCache");
      cache.disableDynamicFeatures();
    In ehcache.xml, you can disable dynamic configuration by setting the <ehcache> element's
      dynamicConfig attribute to "false".

     

     

    解决办法在官方解释中说了,修改dynamicConfig属性为true

     <ehcache updateCheck="false" dynamicConfig="true">  
        <diskStore path="java.io.tmpdir"/>  
        
        <defaultCache  
            maxElementsInMemory="1000"  
            eternal="false"  
            overflowToDisk="true"  
            timeToIdleSeconds="120"  
            timeToLiveSeconds="120"  
            diskPersistent="false"  
            diskExpiryThreadIntervalSeconds="120"  
            memoryStoreEvictionPolicy="LRU"
        />      
         
        <cache name="cache_test" 
            maxElementsInMemory="2"  
            eternal="false"  
            timeToIdleSeconds="60"  
            timeToLiveSeconds="60"  
            maxElementsOnDisk="2"
            overflowToDisk="true"
            diskPersistent="false" 
            memoryStoreEvictionPolicy="FIFO"  
       />   
    </ehcache> 

     

     

    修改之后再次执行下main代码:

        public FirstCache() {
            // 2.创建Cache
            Cache cache = cacheManager.getCache("cache_test");
            CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
            // 2.1获取满了之后的清除策略
            MemoryStoreEvictionPolicy policy = cacheConfiguration.getMemoryStoreEvictionPolicy();
            log.info("{}", cacheConfiguration.getDiskStorePath());
            log.info("{}", cacheConfiguration.getTimeToIdleSeconds());
            log.info("{}", cacheConfiguration.getTimeToLiveSeconds());
            log.info("{}", cacheConfiguration.getMaxElementsInMemory());
            log.info("{}", cacheConfiguration.getMaxElementsOnDisk());
            log.info("{}", cacheConfiguration.getName());
            log.info("{}", policy.toString());
            log.info("===============================");
            
            cacheConfiguration.setDiskStorePath(System.getProperty("java.io.tmpdir"));
            cacheConfiguration.setTimeToIdleSeconds(200);
            cacheConfiguration.setTimeToLiveSeconds(200);
            cacheConfiguration.setMaxElementsInMemory(4);
            cacheConfiguration.setMaxElementsOnDisk(4);
            cacheConfiguration.setName("cache_test_update");
            cacheConfiguration.setMemoryStoreEvictionPolicy("CLOCK");
            MemoryStoreEvictionPolicy policy2 = cacheConfiguration.getMemoryStoreEvictionPolicy();
            log.info("{}", cacheConfiguration.getDiskStorePath());
            log.info("{}", cacheConfiguration.getTimeToIdleSeconds());
            log.info("{}", cacheConfiguration.getTimeToLiveSeconds());
            log.info("{}", cacheConfiguration.getMaxElementsInMemory());
            log.info("{}", cacheConfiguration.getMaxElementsOnDisk());
            log.info("{}", cacheConfiguration.getName());
            log.info("{}", policy2.toString());
        }

     

    结果:(修改生效)

    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] null
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 60
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 60
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 2
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 2
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] cache_test
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] FIFO
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] ===============================
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] C:\Users\liqiang\AppData\Local\Temp\
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 200
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 200
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 4
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 4
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] cache_test_update
    2018-09-09 15:18:46 [encache.FirstCache]-[INFO] CLOCK

     

     

    4.测试上面配置的一些作用:

    修改上面的配置:

        <cache name="cache_test" 
            maxElementsInMemory="2"  
            eternal="false"  
            timeToIdleSeconds="5"  
            timeToLiveSeconds="5"  
            maxElementsOnDisk="2"
            overflowToDisk="true"
            diskPersistent="false" 
            memoryStoreEvictionPolicy="FIFO"  
       />   

     

     

    (1)测试缓存的生存时间:

    package encache;
    
    import java.util.Date;
    import java.util.concurrent.TimeUnit;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import net.sf.ehcache.Cache;
    import net.sf.ehcache.CacheException;
    import net.sf.ehcache.CacheManager;
    import net.sf.ehcache.Element;
    
    public class FirstCache {
        private static final Logger log = LoggerFactory.getLogger(FirstCache.class.getName());
    
        public FirstCache() {
    
            // 1.创建CacheManager
            CacheManager cacheManager = new CacheManager();// 默认读取classpath目录下面的ehcache.xml
    
            // 2.创建Cache
            Cache cache = cacheManager.getCache("cache_test");
    
            // 3.存取元素
            cache.put(new Element("firstCache", "第一个缓存元素"));
    
            // 4.获取元素
            Element element = cache.get("firstCache");
            log.info("获取的缓存元素是:{}", element);
            long creationTime = element.getCreationTime();
            long expirationTime = element.getExpirationTime();
            log.info("creationTime: {}", new Date(creationTime));
            log.info("expirationTime: {}", new Date(expirationTime));
            log.info("diskStoreSize:{}", cache.getDiskStoreSize());
            log.info("cacheSize: {}", cache.getKeys().size());
    
            // 线程休眠6s,使缓存超时
            try {
                // Thread.sleep(6*1000);
                TimeUnit.SECONDS.sleep(7);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            // 再次获取元素
            try {
                Element element1 = cache.get("firstCache");
                long creationTime1 = element1.getCreationTime();
                long expirationTime1 = element1.getExpirationTime();
                log.info("creationTime1: {}", new Date(creationTime1));
                log.info("expirationTime1: {}", new Date(expirationTime1));
            } catch (Exception e) {
                log.error("元素不存在");
            } finally {
                log.info("diskStoreSize:{}", cache.getDiskStoreSize());
                log.info("cacheSize: {}", cache.getKeys().size());
            }
        }
    
        public static void main(String[] args) throws Exception {
            new FirstCache();
        }
    }

     

    查看日志:

    2018-09-09 15:45:55 [net.sf.ehcache.CacheManager]-[DEBUG] Configuring ehcache from classpath.
    2018-09-09 15:45:55 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from ehcache.xml found in the classpath: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
    2018-09-09 15:45:55 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from URL: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
    2018-09-09 15:45:55 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from InputStream
    2018-09-09 15:45:55 [net.sf.ehcache.config.DiskStoreConfiguration]-[DEBUG] Disk Store Path: C:\Users\liqiang\AppData\Local\Temp\
    2018-09-09 15:45:55 [net.sf.ehcache.util.PropertyUtil]-[DEBUG] propertiesString is null.
    2018-09-09 15:45:55 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheManagerEventListenerFactory class specified. Skipping...
    2018-09-09 15:45:56 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
    2018-09-09 15:45:56 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
    2018-09-09 15:45:56 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
    2018-09-09 15:45:56 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
    2018-09-09 15:45:56 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
    2018-09-09 15:45:56 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
    2018-09-09 15:45:56 [net.sf.ehcache.store.MemoryStore]-[DEBUG] Initialized net.sf.ehcache.store.MemoryStore for cache_test
    2018-09-09 15:45:56 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.data
    2018-09-09 15:45:56 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.index
    2018-09-09 15:45:57 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Matching data file missing (or empty) for index file. Deleting index file C:\Users\liqiang\AppData\Local\Temp\cache_test.index
    2018-09-09 15:45:57 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.index
    2018-09-09 15:45:57 [net.sf.ehcache.Cache]-[DEBUG] Initialised cache: cache_test
    2018-09-09 15:45:57 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured. Skipping for 'cache_test'.
    2018-09-09 15:45:57 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured for defaultCache. Skipping for 'cache_test'.
    2018-09-09 15:45:57 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
    2018-09-09 15:45:57 [encache.FirstCache]-[INFO] 获取的缓存元素是:[ key = firstCache, value=第一个缓存元素, version=1, hitCount=1, CreationTime = 1536479157042, LastAccessTime = 1536479157054 ]
    2018-09-09 15:45:57 [encache.FirstCache]-[INFO] creationTime: Sun Sep 09 15:45:57 CST 2018
    2018-09-09 15:45:57 [encache.FirstCache]-[INFO] expirationTime: Sun Sep 09 15:46:02 CST 2018
    2018-09-09 15:45:57 [encache.FirstCache]-[INFO] diskStoreSize:0
    2018-09-09 15:45:57 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
    2018-09-09 15:45:57 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
    2018-09-09 15:45:57 [encache.FirstCache]-[INFO] cacheSize: 1
    2018-09-09 15:46:04 [net.sf.ehcache.store.disk.Segment]-[DEBUG] remove deleted 0 from heap
    2018-09-09 15:46:04 [net.sf.ehcache.store.disk.Segment]-[DEBUG] remove deleted 0 from disk
    2018-09-09 15:46:04 [encache.FirstCache]-[ERROR] 元素不存在
    2018-09-09 15:46:04 [encache.FirstCache]-[INFO] diskStoreSize:0
    2018-09-09 15:46:04 [encache.FirstCache]-[INFO] cacheSize: 0

     

    也就是6s之后缓存会自动清除。缓存时间生效。

     

    (2)测试缓存对象数量问题:

    package encache;
    
    import java.util.Date;
    import java.util.concurrent.TimeUnit;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import net.sf.ehcache.Cache;
    import net.sf.ehcache.CacheException;
    import net.sf.ehcache.CacheManager;
    import net.sf.ehcache.Element;
    
    public class FirstCache {
        private static final Logger log = LoggerFactory.getLogger(FirstCache.class.getName());
    
        public FirstCache() {
    
            // 1.创建CacheManager
            CacheManager cacheManager = new CacheManager();// 默认读取classpath目录下面的ehcache.xml
    
            // 2.创建Cache
            Cache cache = cacheManager.getCache("cache_test");
    
            // 3.存取5个元素
            cache.put(new Element("1", "第1个缓存元素"));
            cache.put(new Element("2", "第2个缓存元素"));
            cache.put(new Element("3", "第3个缓存元素"));
            cache.put(new Element("4", "第4个缓存元素"));
            cache.put(new Element("5", "第5个缓存元素"));
            cache.flush();
    
            try {
                Thread.sleep(2 * 1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            log.info("diskStoreSize:{}", cache.getDiskStoreSize());
            log.info("cacheSize: {}", cache.getKeys().size());
            // 4.获取元素
            for (Object key : cache.getKeys()) {
                log.info("ele:{}", cache.get(key).toString());
            }
    
        }
    
        public static void main(String[] args) throws Exception {
            new FirstCache();
        }
    }

     

    结果:(只获取到最后添加的两个元素。FIFO策略也生效)

    2018-09-09 16:17:11 [net.sf.ehcache.CacheManager]-[DEBUG] Configuring ehcache from classpath.
    2018-09-09 16:17:11 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from ehcache.xml found in the classpath: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
    2018-09-09 16:17:11 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from URL: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
    2018-09-09 16:17:11 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from InputStream
    2018-09-09 16:17:11 [net.sf.ehcache.config.DiskStoreConfiguration]-[DEBUG] Disk Store Path: C:\Users\liqiang\AppData\Local\Temp\
    2018-09-09 16:17:11 [net.sf.ehcache.util.PropertyUtil]-[DEBUG] propertiesString is null.
    2018-09-09 16:17:11 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheManagerEventListenerFactory class specified. Skipping...
    2018-09-09 16:17:13 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
    2018-09-09 16:17:13 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
    2018-09-09 16:17:13 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
    2018-09-09 16:17:13 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
    2018-09-09 16:17:13 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
    2018-09-09 16:17:13 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
    2018-09-09 16:17:13 [net.sf.ehcache.store.MemoryStore]-[DEBUG] Initialized net.sf.ehcache.store.MemoryStore for cache_test
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Matching data file missing (or empty) for index file. Deleting index file C:\Users\liqiang\AppData\Local\Temp\cache_test.index
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.index
    2018-09-09 16:17:13 [net.sf.ehcache.Cache]-[DEBUG] Initialised cache: cache_test
    2018-09-09 16:17:13 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured. Skipping for 'cache_test'.
    2018-09-09 16:17:13 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured for defaultCache. Skipping for 'cache_test'.
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] evicted 0 from disk
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] evicted 0 from heap
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] evicted 0 from disk
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] evicted 0 from heap
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] evicted 0 from disk
    2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] evicted 0 from heap
    2018-09-09 16:17:15 [encache.FirstCache]-[INFO] diskStoreSize:2
    2018-09-09 16:17:15 [encache.FirstCache]-[INFO] cacheSize: 2
    2018-09-09 16:17:15 [encache.FirstCache]-[INFO] ele:[ key = 5, value=第5个缓存元素, version=1, hitCount=1, CreationTime = 1536481034000, LastAccessTime = 1536481035344 ]
    2018-09-09 16:17:15 [encache.FirstCache]-[INFO] ele:[ key = 4, value=第4个缓存元素, version=1, hitCount=1, CreationTime = 1536481034000, LastAccessTime = 1536481035347 ]

     

     

    3.defaultCache的作用

      一直以为defaultCache的配置是会给我们创建一个cache,实际上是在程序中创建的cache会默认采用此配置。

     

    在encache-core的包下面的ehcache-failsafe.xml的描述如下:

        <!--
        Mandatory Default Cache configuration. These settings will be applied to caches
        created programmtically using CacheManager.add(String cacheName)
        -->
        <defaultCache
                maxElementsInMemory="10000"
                eternal="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                overflowToDisk="true"
                maxElementsOnDisk="10000000"
                diskPersistent="false"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU"
                />

     

     

    也就是程序中显示创建的Cache会默认使用defaultCache的配置。

     

    package encache;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import net.sf.ehcache.Cache;
    import net.sf.ehcache.CacheManager;
    import net.sf.ehcache.config.CacheConfiguration;
    import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
    
    public class FirstCache {
        private static final Logger log = LoggerFactory.getLogger(FirstCache.class.getName());
    
        public FirstCache() {
    
            // 1.创建CacheManager
            CacheManager cacheManager = CacheManager.create();
    
            // 2.创建并且获取Cache
            cacheManager.addCache("dynamic_cache");
            Cache cache = cacheManager.getCache("dynamic_cache");
            CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
            // 2.1获取满了之后的清除策略
            MemoryStoreEvictionPolicy policy = cacheConfiguration.getMemoryStoreEvictionPolicy();
            log.info("{}", cacheConfiguration.getDiskStorePath());
            log.info("{}", cacheConfiguration.getTimeToIdleSeconds());
            log.info("{}", cacheConfiguration.getTimeToLiveSeconds());
            log.info("{}", cacheConfiguration.getMaxElementsInMemory());
            log.info("{}", cacheConfiguration.getMaxElementsOnDisk());
            log.info("{}", cacheConfiguration.getName());
            log.info("{}", policy.toString());
    
        }
    
        public static void main(String[] args) throws Exception {
            new FirstCache();
        }
    }

     

    结果:

    2018-09-09 16:51:27 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from ehcache.xml found in the classpath: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
    2018-09-09 16:51:27 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from URL: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
    2018-09-09 16:51:27 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from InputStream
    2018-09-09 16:51:27 [net.sf.ehcache.config.DiskStoreConfiguration]-[DEBUG] Disk Store Path: C:\Users\liqiang\AppData\Local\Temp\
    2018-09-09 16:51:27 [net.sf.ehcache.CacheManager]-[DEBUG] Creating new CacheManager with default config
    2018-09-09 16:51:27 [net.sf.ehcache.util.PropertyUtil]-[DEBUG] propertiesString is null.
    2018-09-09 16:51:27 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheManagerEventListenerFactory class specified. Skipping...
    2018-09-09 16:51:29 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
    2018-09-09 16:51:29 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
    2018-09-09 16:51:29 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
    2018-09-09 16:51:29 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
    2018-09-09 16:51:29 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
    2018-09-09 16:51:29 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
    2018-09-09 16:51:29 [net.sf.ehcache.store.MemoryStore]-[DEBUG] Initialized net.sf.ehcache.store.MemoryStore for cache_test
    2018-09-09 16:51:29 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Matching data file missing (or empty) for index file. Deleting index file C:\Users\liqiang\AppData\Local\Temp\cache_test.index
    2018-09-09 16:51:29 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.index
    2018-09-09 16:51:29 [net.sf.ehcache.Cache]-[DEBUG] Initialised cache: cache_test
    2018-09-09 16:51:29 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured. Skipping for 'cache_test'.
    2018-09-09 16:51:29 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured for defaultCache. Skipping for 'cache_test'.
    2018-09-09 16:51:29 [net.sf.ehcache.store.MemoryStore]-[DEBUG] Initialized net.sf.ehcache.store.MemoryStore for dynamic_cache
    2018-09-09 16:51:29 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file dynamic_cache.data
    2018-09-09 16:51:29 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file dynamic_cache.index
    2018-09-09 16:51:29 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Matching data file missing (or empty) for index file. Deleting index file C:\Users\liqiang\AppData\Local\Temp\dynamic_cache.index
    2018-09-09 16:51:29 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file dynamic_cache.index
    2018-09-09 16:51:29 [net.sf.ehcache.Cache]-[DEBUG] Initialised cache: dynamic_cache
    2018-09-09 16:51:29 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured for defaultCache. Skipping for 'dynamic_cache'.
    2018-09-09 16:51:29 [encache.FirstCache]-[INFO] null
    2018-09-09 16:51:29 [encache.FirstCache]-[INFO] 120
    2018-09-09 16:51:29 [encache.FirstCache]-[INFO] 120
    2018-09-09 16:51:29 [encache.FirstCache]-[INFO] 1000
    2018-09-09 16:51:29 [encache.FirstCache]-[INFO] 0
    2018-09-09 16:51:29 [encache.FirstCache]-[INFO] dynamic_cache
    2018-09-09 16:51:29 [encache.FirstCache]-[INFO] LRU

     

    4.encache原码分析:

    CacheManager

      一个普通的class,里面包含管理cache的信息

    public class CacheManager {
    
        /**
         * Default name if not specified in the configuration/
         */
        public static final String DEFAULT_NAME = "__DEFAULT__";
    
        /**
         * Threshold, in percent of the available heap, above which the CacheManager will warn if the configured memory
         */
        public static final double ON_HEAP_THRESHOLD = 0.8;
    
        /**
         * Keeps track of all known CacheManagers. Used to check on conflicts.
         * CacheManagers should remove themselves from this list during shut down.
         */
        public static final List<CacheManager> ALL_CACHE_MANAGERS = new CopyOnWriteArrayList<CacheManager>();
    
        /**
         * System property to enable creation of a shutdown hook for CacheManager.
         */
        public static final String ENABLE_SHUTDOWN_HOOK_PROPERTY = "net.sf.ehcache.enableShutdownHook";
    
        private static final Logger LOG = LoggerFactory.getLogger(CacheManager.class);
    
        /**
         * Update check interval - one week in milliseconds
         */
        private static final long EVERY_WEEK = 7 * 24 * 60 * 60 * 1000;
    
      
        private static final long DELAY_UPDATE_CHECK = 1000;
    
       
        private static volatile CacheManager singleton;
    
    
        private static final MBeanRegistrationProviderFactory MBEAN_REGISTRATION_PROVIDER_FACTORY = new MBeanRegistrationProviderFactoryImpl();
    
        private static final String NO_DEFAULT_CACHE_ERROR_MSG = "Caches cannot be added by name when default cache config is not specified"
                + " in the config. Please add a default cache config in the configuration.";
    
        private static final Map<String, CacheManager> CACHE_MANAGERS_MAP = new HashMap<String, CacheManager>();
    
        private static final IdentityHashMap<CacheManager, String> CACHE_MANAGERS_REVERSE_MAP = new IdentityHashMap<CacheManager, String>();
    
    
        protected volatile Status status;
    
        protected final Map<String, CacheManagerPeerProvider> cacheManagerPeerProviders = new ConcurrentHashMap<String, CacheManagerPeerProvider>();
    
     
        protected final Map<String, CacheManagerPeerListener> cacheManagerPeerListeners = new ConcurrentHashMap<String, CacheManagerPeerListener>();
    
        
        protected final CacheManagerEventListenerRegistry cacheManagerEventListenerRegistry = new CacheManagerEventListenerRegistry();
    
        
        protected Thread shutdownHook;
    
    
        private final ConcurrentMap<String, Ehcache> ehcaches = new ConcurrentHashMap<String, Ehcache>();

     ehcaches里面存放的是一个一个的cache。

     

    Cache:

    public class Cache implements InternalEhcache, StoreListener {
    
    
        public static final String DEFAULT_CACHE_NAME = "default";
    
    
        public static final String NET_SF_EHCACHE_DISABLED = "net.sf.ehcache.disabled";
    
    
        public static final String NET_SF_EHCACHE_USE_CLASSIC_LRU = "net.sf.ehcache.use.classic.lru";
    
    
        public static final long DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS = CacheConfiguration.DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS;
    
    
        public static final String OFF_HEAP_STORE_CLASSNAME = "net.sf.ehcache.store.offheap.OffHeapStore";
    
        private static final Logger LOG = LoggerFactory.getLogger(Cache.class.getName());

     private volatile Store compoundStore; 用于存放真正的元素。

     

    Element:

      一个实现serializable和clonable的普通类,里面有key和value以及一些其他信息:

    public class Element implements Serializable, Cloneable {
    
        private static final long serialVersionUID = 1098572221246444544L;
    
        private static final Logger LOG = LoggerFactory.getLogger(Element.class.getName());
    
        private static final AtomicLongFieldUpdater<Element> HIT_COUNT_UPDATER = AtomicLongFieldUpdater.newUpdater(Element.class, "hitCount");
    
        private static final boolean ELEMENT_VERSION_AUTO = Boolean.getBoolean("net.sf.ehcache.element.version.auto");
    
        static {
            if (ELEMENT_VERSION_AUTO) {
                LOG.warn("Note that net.sf.ehcache.element.version.auto is set and user provided version will not be honored");
            }
        }
    
    
        @IgnoreSizeOf
        private final Object key;
    
    
        private final Object value;
    
    
        private volatile long version;
    
    
        private volatile long hitCount;
    
    
        private volatile int timeToLive = Integer.MIN_VALUE;
    
        private volatile int timeToIdle = Integer.MIN_VALUE;
    
    
        private transient volatile ElementEvictionData elementEvictionData;
    
    
        private volatile long lastUpdateTime;
    
        private volatile boolean cacheDefaultLifespan = true;

     

      Encache也可以进行集群等高级操作,待用到的时候查阅API即可。encache是新开一个线程进行缓存管理,JVM不停此线程也不会停止。

     

    补充:在一个JVM如果创建两个名字相同的cache,则会报错,如下:

    package encache;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import net.sf.ehcache.CacheManager;
    
    public class SecondCache {
        private static final Logger log = LoggerFactory.getLogger(SecondCache.class.getName());
    
        public static void main(String[] args) throws Exception {
            // 1.创建CacheManager
            final CacheManager cacheManager = CacheManager.create();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    cacheManager.addCache("dynamic_cache");
                }
            }).start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    cacheManager.addCache("dynamic_cache");
                }
            }).start();
        }
    }

     

    结果:

    Exception in thread "Thread-1" net.sf.ehcache.ObjectExistsException: Cache dynamic_cache already exists
    at net.sf.ehcache.CacheManager.addCacheNoCheck(CacheManager.java:1294)
    at net.sf.ehcache.CacheManager.addCache(CacheManager.java:1184)
    at net.sf.ehcache.CacheManager.addCache(CacheManager.java:1126)
    at encache.SecondCache$1.run(SecondCache.java:17)
    at java.lang.Thread.run(Thread.java:745)

     

    补充:Element有一个构造方法可以指定缓存的时间等参数

    package encache;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import net.sf.ehcache.Cache;
    import net.sf.ehcache.CacheManager;
    import net.sf.ehcache.Element;
    
    public class FirstCache {
        private static final Logger log = LoggerFactory.getLogger(FirstCache.class.getName());
    
        public FirstCache() {
    
            // 1.创建CacheManager
            CacheManager cacheManager = new CacheManager();// 默认读取classpath目录下面的ehcache.xml
    
            // 2.创建Cache
            Cache cache = cacheManager.getCache("cache_test");
    
            // 3.添加元素
            cache.put(new Element("key", "value", false, 0, 12));
    
            // 4.休眠5秒钟获取元素
            try {
                Thread.sleep(5 * 1000);
            } catch (InterruptedException e) {
            }
            Element element = cache.get("key");
            System.out.println(element);
    
            // 4.休眠13秒钟获取元素
            try {
                Thread.sleep(13 * 1000);
            } catch (InterruptedException e) {
            }
            // 4.获取元素
            Element element2 = cache.get("key");
            System.out.println(element2);
    
        }
    
        public static void main(String[] args) throws Exception {
            new FirstCache();
        }
    }

     

    结果:

    [ key = key, value=value, version=0, hitCount=1, CreationTime = 1544537618418, LastAccessTime = 1544537623428 ]
    null

     

    补充:在学习了多线程之后对ehcache缓存进行的实验多线程环境下

    package encache;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import net.sf.ehcache.Cache;
    import net.sf.ehcache.CacheManager;
    import net.sf.ehcache.Element;
    
    public class SecondCache {
        private static final Logger log = LoggerFactory.getLogger(SecondCache.class.getName());
    
        public static void main(String[] args) throws Exception {
            // 1.创建CacheManager
            final CacheManager cacheManager = CacheManager.create();
            // 开启线程创建cache
            new Thread(new Runnable() {
                @Override
                public void run() {
                    log.info("添加缓存->{},threadName->{}", "dynamic_cache", Thread.currentThread().getName());
                    cacheManager.addCache("dynamic_cache");
                }
            }, "A").start();
            // 添加元素
            Thread.sleep(1 * 1000);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Cache cache = cacheManager.getCache("dynamic_cache");
                    for (int i = 0; i < 5; i++) {
                        Map<String, Object> cacheEle = new HashMap<>();
                        cacheEle.put("" + i, "第" + i + "个元素");
                        log.info("添加缓存元素->{},threadName->{}", cacheEle, Thread.currentThread().getName());
                        cache.put(new Element(i + "key", cacheEle));
                    }
    
                    // 覆盖第二个元素
                    Map<String, Object> cacheEle = new HashMap<>();
                    cacheEle.put("" + 2, "第" + 22222 + "个元素");
                    cache.put(new Element(2 + "key", cacheEle));
                    log.info("覆盖缓存元素->{},threadName->{}", 2 + "key", Thread.currentThread().getName());
                    cache.flush();
                }
            }, "B").start();
            // 访问元素
            Thread.sleep(1 * 1000);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Cache cache = cacheManager.getCache("dynamic_cache");
                    for (Object key : cache.getKeys()) {
                        log.info("获取缓存元素key->{},value->{},threadName->{}", new Object[] { key,
                                (Map) cache.get(key).getObjectValue(), Thread.currentThread().getName() });
                    }
                }
            }, "C").start();
    
        }
    }

     

    结果:

    2018-12-11 21:53:10 [encache.SecondCache]-[INFO] 添加缓存->dynamic_cache,threadName->A
    2018-12-11 21:53:11 [encache.SecondCache]-[INFO] 添加缓存元素->{0=第0个元素},threadName->B
    2018-12-11 21:53:11 [encache.SecondCache]-[INFO] 添加缓存元素->{1=第1个元素},threadName->B
    2018-12-11 21:53:11 [encache.SecondCache]-[INFO] 添加缓存元素->{2=第2个元素},threadName->B
    2018-12-11 21:53:11 [encache.SecondCache]-[INFO] 添加缓存元素->{3=第3个元素},threadName->B
    2018-12-11 21:53:11 [encache.SecondCache]-[INFO] 添加缓存元素->{4=第4个元素},threadName->B
    2018-12-11 21:53:11 [encache.SecondCache]-[INFO] 覆盖缓存元素->2key,threadName->B
    2018-12-11 21:53:12 [encache.SecondCache]-[INFO] 获取缓存元素key->4key,value->{4=第4个元素},threadName->C
    2018-12-11 21:53:12 [encache.SecondCache]-[INFO] 获取缓存元素key->1key,value->{1=第1个元素},threadName->C
    2018-12-11 21:53:12 [encache.SecondCache]-[INFO] 获取缓存元素key->3key,value->{3=第3个元素},threadName->C
    2018-12-11 21:53:12 [encache.SecondCache]-[INFO] 获取缓存元素key->0key,value->{0=第0个元素},threadName->C
    2018-12-11 21:53:12 [encache.SecondCache]-[INFO] 获取缓存元素key->2key,value->{2=第22222个元素},threadName->C

     

    补充:自己封装的一个工具类以及简单的测试:

    package ehcache;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import net.sf.ehcache.Cache;
    import net.sf.ehcache.CacheManager;
    import net.sf.ehcache.Element;
    import net.sf.ehcache.config.CacheConfiguration;
    import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
    
    public class EhcacheUtils {
        public static final String CACHE_NAME1 = "cache1";
        public static final String CACHE_NAME2 = "cache2";
    
        public static final int CACHE_ONE_HOUR = 1 * 60 * 60;
        public static final int CACHE_ONE_DAY = 24 * 60 * 60;
    
        private static CacheManager cacheManager = CacheManager.create();
        // 静态代码块创建缓存
        static {
            cacheManager.addCache(CACHE_NAME1);
            cacheManager.addCache(CACHE_NAME2);
    
            initCacheSettings(cacheManager.getCache(CACHE_NAME1));
            initCacheSettings(cacheManager.getCache(CACHE_NAME2));
        }
    
        private static void initCacheSettings(Cache cache) {
            CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
            cacheConfiguration.setTimeToIdleSeconds(8 * 60 * 60);
            cacheConfiguration.setTimeToLiveSeconds(24 * 60 * 60);
            // cacheConfiguration.setMaxElementsInMemory(4);
            // cacheConfiguration.setMaxElementsOnDisk(4);
            // cacheConfiguration.setName("cache_test_update");
            cacheConfiguration.setMemoryStoreEvictionPolicy("CLOCK");
        }
    
        private EhcacheUtils() {
    
        }
    
        // 1.增加元素
        /**
         * 向指定的缓存中增加元素
         * 
         * @param cacheName
         *            缓存名称
         * @param key
         *            缓存的key
         * @param value
         *            缓存d值
         * @param seconds
         *            缓存的时间(秒)
         * @param override
         *            如果存在是否覆盖
         * @return
         */
        public static boolean addCache(String cacheName, String key, Object value, int seconds, boolean override) {
            try {
                Cache cache = cacheManager.getCache(cacheName);
                Object tmpValue = getValueByCacheKey(cacheName, key);
                if (tmpValue != null) {
                    if (!override) {
                        return true;
                    }
                }
                cache.put(new Element(key, value, false, 0, seconds));
                cache.flush();
                return true;
            } catch (Exception e) {
                return false;
            }
        }
    
        // 2.删除元素
        // 2.1删除单个元素
        /**
         * 删除单个元素
         * 
         * @param cacheName
         *            缓存的名称
         * @param key
         *            缓存的key
         * @return
         */
        public static boolean removeCacheByKey(String cacheName, String key) {
            try {
                Cache cache = cacheManager.getCache(cacheName);
                cache.remove(key);
                return true;
            } catch (Exception e) {
                return false;
            }
        }
    
        // 2.2删除全部元素
        /**
         * 删除所有元素
         * 
         * @param cacheName
         *            缓存名称
         * @return
         */
        public static boolean removeAllByCacheName(String cacheName) {
            try {
                Cache cache = cacheManager.getCache(cacheName);
                cache.removeAll();
                return true;
            } catch (Exception e) {
                return false;
            }
        }
    
        // 3.获取元素
        // 3.1获取单个元素
        /**
         * 获取单个元素
         * 
         * @param cacheName
         *            缓存名称
         * @param key
         *            缓存的key
         * @return
         */
        public static Object getValueByCacheKey(String cacheName, String key) {
            try {
                Cache cache = cacheManager.getCache(cacheName);
                Element element = cache.get(key);
                return element == null ? null : element.getObjectValue();
            } catch (Exception e) {
                return null;
            }
        }
    
        // 3.1获取全部元素
        /**
         * 获取所有缓存d元素
         * 
         * @param cacheName
         *            缓存的名称
         * @return
         */
        public static List<Object> getAllValuesByCacheName(String cacheName) {
            List<Object> result = new ArrayList<Object>();
            try {
                Cache cache = cacheManager.getCache(cacheName);
                for (Object key : cache.getKeys()) {
                    Element element = cache.get(key);
                    result.add(element.getObjectValue());
                }
                return result;
            } catch (Exception e) {
                return result;
            }
        }
    
        // 4.获取配置
        public static Map<String, String> getConfigurations(String cacheName) {
            Map<String, String> results = new HashMap<String, String>();
            Cache cache = cacheManager.getCache(cacheName);
            CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
    
            MemoryStoreEvictionPolicy policy = cacheConfiguration.getMemoryStoreEvictionPolicy();
            results.put("timeToIdleSeconds", String.valueOf(cacheConfiguration.getTimeToIdleSeconds()));
            results.put("timeToLiveSeconds", String.valueOf(cacheConfiguration.getTimeToLiveSeconds()));
            results.put("maxElementsInMemory", String.valueOf(cacheConfiguration.getMaxElementsInMemory()));
            results.put("policy", policy.toString());
            return results;
        }
    }

     ehcache.xml

    <ehcache updateCheck="false" dynamicConfig="true">  
        <diskStore path="java.io.tmpdir"/>  
        
        <defaultCache  
            maxElementsInMemory="1000"  
            eternal="false"  
            overflowToDisk="true"  
            timeToIdleSeconds="120"  
            timeToLiveSeconds="120"  
            diskPersistent="false"  
            diskExpiryThreadIntervalSeconds="120"  
            memoryStoreEvictionPolicy="LRU"
        />      
    </ehcache>

     

    测试代码:

            List<String> cache1 = new ArrayList<>();
            cache1.add("111");
            cache1.add("222");
    
            EhcacheUtils.addCache(EhcacheUtils.CACHE_NAME1, "cache1", cache1, EhcacheUtils.CACHE_ONE_HOUR, false);
    
            String cache2 = "cache2";
            EhcacheUtils.addCache(EhcacheUtils.CACHE_NAME1, "cache2", cache2, EhcacheUtils.CACHE_ONE_HOUR, false);
    
            Map cache3 = new HashMap();
            cache3.put("1", "111222");
            cache3.put("2", "111222333");
            EhcacheUtils.addCache(EhcacheUtils.CACHE_NAME1, "cache3", cache3, EhcacheUtils.CACHE_ONE_HOUR, false);
    
            Map valueByCacheKey = (Map) EhcacheUtils.getValueByCacheKey(EhcacheUtils.CACHE_NAME1, "cache3");
            System.out.println(valueByCacheKey);
    
            EhcacheUtils.removeCacheByKey(EhcacheUtils.CACHE_NAME1, "cache2");
            List<Object> allValuesByCacheName = EhcacheUtils.getAllValuesByCacheName(EhcacheUtils.CACHE_NAME1);
            for (Object obj : allValuesByCacheName) {
                System.out.println(obj);
            }
    
            Map<String, String> configurations = EhcacheUtils.getConfigurations(EhcacheUtils.CACHE_NAME1);
            System.out.println(configurations);

    结果:(线程也没有停止)

     

    采用JVisualVM查看线程信息: (主线程结束了,但是仍然有ehcache创建的用户线程,有3个用户线程----创建CacheManager的时候会创建一个守护线程Statisxxxx,每次创建一个cache的时候也会创建一个用户线程 cacheName.data)

     

    源代码跟踪解释线程:

    (1)在  调用CacheManager cacheManager = CacheManager.create();   创建CacheManager的时候创建一个守护线程Statistics thread-_default_-1  统计线程

        public CacheManager(String configurationFileName) throws CacheException {
            status = Status.STATUS_UNINITIALISED;
            init(null, configurationFileName, null, null);
        }

     

     

    init中调用doInit(...)

     

    doInit(...)创建线程(用到线程池进行周期性调用---此线程是一个守护线程)

            statisticsExecutor = Executors.newScheduledThreadPool(
              Integer.getInteger("net.sf.ehcache.CacheManager.statisticsExecutor.poolSize", 1) ,
    
              new ThreadFactory() {
                 private AtomicInteger cnt = new AtomicInteger(0);
                 @Override
                 public Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "Statistics Thread-" + getName() + "-" + cnt.incrementAndGet());
                    t.setDaemon(true);
                    return t;
                 }
              });

     

     

    (2)在调用cacheManager.addCache("cache1");的时候创建一个用户线程:cache1.data (所以主线程结束,此线程也没有结束,进程也没有结束)

            ...这个代码暂时没有根出来,只是根到调用此方法后创建了一个用户线程

     

    最完美的就是再写一个key生成器,KeyGenerator可以参考下面代码:

    package cn.xm.jwxt.utils;
    
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 22:49 2018/3/25
     */
    public class KeyGenerator implements org.springframework.cache.interceptor.KeyGenerator {
        @Override
        public Object generate(Object o, Method method, Object... params) {
            //规定  本类名+方法名+参数名 为key
            StringBuilder sb = new StringBuilder();
            sb.append(o.getClass().getName());
            sb.append(method.getName());
            for (Object param : params) {
                sb.append(param.toString());
            }
            return sb.toString();
        }
    }

     

    展开全文
  • EHCache_技术文档

    2011-09-13 19:09:10
    EHCache_技术文档 EHCache缓存 spring缓存
  • Ehcache API

    热门讨论 2009-03-20 10:33:06
    Ehcache官方 API Ehcache官方 API
  • Ehcache原理详细解读

    2022-05-11 15:49:06
    网上中文EhCache材料以简单介绍和配置方法居多,对于API,官网上介绍已经非常清楚,请参见官网;但是很少见到特性说明和对实现原理的分析,因此在这篇文章里面,详细介绍和分析EhCache的特性,加上一些自己的理解...
  • 包含翻译后的API文档:ehcache-3.3.1-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.ehcache:ehcache:3.3.1; 标签:ehcache、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用...
  • 包含翻译后的API文档:ehcache-web-2.0.4-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:net.sf.ehcache:ehcache-web:2.0.4; 标签:sf、ehcache、web、中英对照文档、jar包、java; 使用方法:解压翻译...
  • 包含翻译后的API文档:shiro-ehcache-1.2.3-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.apache.shiro:shiro-ehcache:1.2.3; 标签:apache、shiro、ehcache、中英对照文档、jar包、java; 使用...
  • 包含翻译后的API文档:shiro-ehcache-1.4.0-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.apache.shiro:shiro-ehcache:1.4.0; 标签:apache、shiro、ehcache、中英对照文档、jar包、java; 使用...
  • Ehcache经典中文教程

    热门讨论 2013-08-23 11:16:27
    Ehcache经典中文教程Ehcache内存框架介绍 —高成勇 安装 配置 编码接口介绍 api
  • 包含翻译后的API文档:shiro-ehcache-1.3.2-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.apache.shiro:shiro-ehcache:1.3.2; 标签:apache、shiro、ehcache、中英对照文档、jar包、java; 使用...
  • ehcache是一个很成熟的基于jvm内存的缓存框架,其效率是要比redis基于socket要高的,一般ehcache可以配合数据库做一个缓存中间件来减少数据库的访问压力。 见过很多人包括我自己之前也有这样的疑问:ehcache比jvm的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,505
精华内容 2,202
关键字:

ehcache 中文