Ehcache 3.7文档—基础篇—JCache aka JSR-107

一. 概述JCachehtml

Java临时缓存API(JSR-107),也被称为JCache,它是一个规范在javax.cache.API中定义的。该规范是在Java Community Process下开发的,它的目的是为java应用程序提供一个标准的缓存概念和机制。java

这套API用起来很方便,它被设计成缓存标准而且是平台无关的,它消除了过去不一样供应商之间API是不一样的,这致使开发人员坚持使用他们已经使用的专有API,而不是研究新的API,由于研究其余产品的门槛过高了。编程

做为应用程序开发人员,您能够很容易地使用来自某个供应商的JCache API开发应用程序,若是您愿意,能够尝试使用其余供应商的JCache实现,而不须要更改应用程序的任何一行代码。您所要作的就是使用所选供应商的JCache缓存库。这意味着您能够避免在应用程序中为了尝试新的缓存解决方案而重写大量与缓存相关的代码。api

 

二. 使用Ehcache为JCache提供实现缓存

为了在应用程序中使用JCache的API,你须要下面的两个jar包:dom

  • JCache的jar包,它定义了JCache的API接口
  • Ehcache的jar包,它实现JCache中的接口,将JCache的调用转换成Ehcache的调用。

你可使用JCacheAPI去开发一个完整的应用,不须要调用任何Ehcache的API。ide

 

三. 开始使用Ehcache和JCacheui

JCache规范除了定义Cache接口,还定义了CachingProvider和CacheManager规范。应用程序须要使用CacheManager去建立/获取一个cache,一样的使用CachingProvider去获取/访问CacheManager.atom

下面有个代码样例显示了基本JCache配置的API:spa

CachingProvider provider = Caching.getCachingProvider(); (1) CacheManager cacheManager = provider.getCacheManager(); (2) MutableConfiguration<Long, String> configuration =
    new MutableConfiguration<Long, String>() (3) .setTypes(Long.class, String.class) (4) .setStoreByValue(false) (5) .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_MINUTE)); (6) Cache<Long, String> cache = cacheManager.createCache("jCache", configuration); (7) cache.put(1L, "one"); (8) String value = cache.get(1L);(9)

(1). 从应用程序的classpath中得到一个默认的CachingProvider实现。当classpath中只有一个实现时这个方法才能够正常使用。若是classpath中有多个实现,那么使用全限定名org.ehcache.jsr107.EhcacheCachingProvider去获取Ehcache的实现。你能够经过使用静态方法Caching.getCachingProvider(String)来实现这一点。

(2). 经过Provider来获取默认的CacheManager

(3). 使用MutableConfiguration建立一个cache配置

(4). 设置key-type和value-type

(5). 设置经过引用存储cache entries

(6). 设置过时时间为从建立的那一刻起以后的一分钟

(7). 使用CacheManager和第三步建立的configuration,建立一个名为JCache的cache

(8). 向cache中存入一些数据

(9). 从cache中获取数据

 

四. 集成JCache和Ehcache的配置

正如前面提到的,JCache提供了一组最小的配置,对于内存缓存很是理想。可是Ehcache原生api支持复杂得多的拓扑,而且提供了更多的特性。有时,应用程序开发人员可能但愿配置比JCache MutableConfiguration容许的缓存复杂得多的缓存(就拓扑或特性而言),同时仍然可以使用JCache缓存的api。因此Ehcache提供了几种实现此目的的方法,以下面的部分所述。

1. 经过JCache配置访问底层的Ehcache配置

    当你使用CacheManager和MutableConfiguration建立Cache,换句话说只是用JCache类型时,你仍然能够访问底层的Ehcache CacheRuntimeConfiguration:

MutableConfiguration<Long, String> configuration = new MutableConfiguration<>(); configuration.setTypes(Long.class, String.class); Cache<Long, String> cache = cacheManager.createCache("someCache", configuration);(1) CompleteConfiguration<Long, String> completeConfiguration = cache.getConfiguration(CompleteConfiguration.class); (2) Eh107Configuration<Long, String> eh107Configuration = cache.getConfiguration(Eh107Configuration.class); (3) CacheRuntimeConfiguration<Long, String> runtimeConfiguration = eh107Configuration.unwrap(CacheRuntimeConfiguration.class); (4)

(1). 使用JCache规范中的MutableConfiuration接口建立JCache cache

(2). 获取CompleteConfiguration

(3). 获取链接Ehcache和JCache的配置桥

(4). 换成CacheRuntimeConfiguration类型

 

2. 使用Ehcache API构建JCache配置

若是你须要在CacheManager级别配置,就像持久化目录那样,你须要使用特定的API,你能够像下面这么作:

CachingProvider cachingProvider = Caching.getCachingProvider(); EhcacheCachingProvider ehcacheProvider = (EhcacheCachingProvider) cachingProvider; (1) DefaultConfiguration configuration = new DefaultConfiguration(ehcacheProvider.getDefaultClassLoader(), new DefaultPersistenceConfiguration(getPersistenceDirectory())); (2) CacheManager cacheManager = ehcacheProvider.getCacheManager(ehcacheProvider.getDefaultURI(), configuration); (3)

(1). 转换CachingProvider为Ehcache指定的实现org.ehcache.jsr107.EhcacheCachingProvider

(2). 使用指定的Ehcache DefaultConfiguration建立一个configuration并把它传给CacheManager级别的配置中

(3). 使用参数为Ehcache configuration的方法建立CacheManager

 

3. 缓存级别配置

还可使用Ehcache CacheConfiguration建立JCache缓存。当使用此机制时,没有使用JCache complete teconfiguration,所以您不能使用它

CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)).build(); (1) Cache<Long, String> cache = cacheManager.createCache("myCache", Eh107Configuration.fromEhcacheCacheConfiguration(cacheConfiguration)); (2) Eh107Configuration<Long, String> configuration = cache.getConfiguration(Eh107Configuration.class); configuration.unwrap(CacheConfiguration.class); (3) configuration.unwrap(CacheRuntimeConfiguration.class); (4) try { cache.getConfiguration(CompleteConfiguration.class); (5) throw new AssertionError("IllegalArgumentException expected"); } catch (IllegalArgumentException iaex) { // Expected
}

(1). 你可使用象上面使用的构建器或者使用XML配置来建立Ehcache CacheConfiguration

(2). 经过包装Ehcache配置得到JCache配置

(3). 获取Ehcache CacheConfiguration

(4). 获取运行时配置

(5). 在这个上下文中没有JCache CompleteConfiguration能够得到

 

4. 使用Ehcache XML配置构建JCache配置

JCache缓存上拥有完整的Ehcache配置选项的另外一种方法是使用基于xml的配置,有关用XML配置缓存的更多细节,请参阅XML文档。下面是一个XML配置的例子:

<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-3.0.xsd">

  <cache alias="ready-cache">
    <key-type>java.lang.Long</key-type>
    <value-type>com.pany.domain.Product</value-type>
    <loader-writer>
      <class>com.pany.ehcache.integration.ProductCacheLoaderWriter</class>
    </loader-writer>
    <heap unit="entries">100</heap>
  </cache>

</config>

下面是如何使用JCache访问XML配置的示例:

CachingProvider cachingProvider = Caching.getCachingProvider(); CacheManager manager = cachingProvider.getCacheManager( (1) getClass().getResource("/org/ehcache/docs/ehcache-jsr107-config.xml").toURI(), (2) getClass().getClassLoader()); (3) Cache<Long, Product> readyCache = manager.getCache("ready-cache", Long.class, Product.class); (4)

(1). 调用javax.cache.spi.CachingProvider.getCacheManager(java.net.URI, java.lang.ClassLoader)

(2). 而且传入URI,它解析为Ehcache XML配置文件

(3). 第二个参数是ClassLoader,在须要时用于加载用户类型,Class实例存储在由CacheManager管理的Cache中

(4). 从CacheManager中获取Cache

 

5. 使用/禁止 MBeans

当使用Ehcache XML配置时,您可能但愿为JCache缓存启用管理或统计mbean。这使您能够控制如下内容:

  • javax.cache.configuration.CompleteConfiguration.isStatisticsEnabled

  • javax.cache.configuration.CompleteConfiguration.isManagementEnabled

您能够在两个不一样的级别上这样作:

<config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns='http://www.ehcache.org/v3' xmlns:jsr107='http://www.ehcache.org/v3/jsr107' xsi:schemaLocation="         http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
        http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">


  <service>
    <jsr107:defaults enable-management="true" enable-statistics="true"/> (1)
  </service>

  <cache alias="stringCache"> (2)
    <key-type>java.lang.String</key-type>
    <value-type>java.lang.String</value-type>
    <heap unit="entries">2000</heap>
  </cache>

  <cache alias="overrideCache">
    <key-type>java.lang.String</key-type>
    <value-type>java.lang.String</value-type>
    <heap unit="entries">2000</heap>
    <jsr107:mbeans enable-management="false" enable-statistics="false"/> (3)
  </cache>

  <cache alias="overrideOneCache">
    <key-type>java.lang.String</key-type>
    <value-type>java.lang.String</value-type>
    <heap unit="entries">2000</heap>
    <jsr107:mbeans enable-statistics="false"/> (4)
  </cache>
</config>

(1). 使用JCache服务扩展,默认状况下能够启用MBean
(2). 根据服务配置,缓存stringCache将启用这两个MBean
(3). 缓存overrideCache将禁用两个MBean
(4). 缓存overrideOneCache将禁用统计MBean,而管理MBean将根据服务配置启用

 

6. 使用EhcacheXML扩展来补充JCache的配置

您还能够建立cache-templates。有关详细信息,请参阅XML文档的缓存模板部分。Ehcache做为JCache的缓存的实现,提供了对常规XML配置的扩展,因此你能够:

  • 配置一个默认模板,全部以编程方式建立的缓存实例都继承该模板
  • 配置给定的命名缓存以从特定模板继承。

这个特性对于配置超出JCache规范范围的缓存特别有用,例如为缓存提供容量约束。为此在XML configura中添加一个jsr107服务

<config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns='http://www.ehcache.org/v3' xmlns:jsr107='http://www.ehcache.org/v3/jsr107' xsi:schemaLocation="         http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
        http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd"> (1)

  <service> (2)
    <jsr107:defaults default-template="tinyCache"> (3)
      <jsr107:cache name="foos" template="clientCache"/> (4)
      <jsr107:cache name="byRefCache" template="byRefTemplate"/>
      <jsr107:cache name="byValCache" template="byValueTemplate"/>
      <jsr107:cache name="weirdCache1" template="mixedTemplate1"/>
      <jsr107:cache name="weirdCache2" template="mixedTemplate2"/>
    </jsr107:defaults>
  </service>

  <cache-template name="clientCache">
    <key-type>java.lang.String</key-type>
    <value-type>com.pany.domain.Client</value-type>
    <expiry>
      <ttl unit="minutes">2</ttl>
    </expiry>
    <heap unit="entries">2000</heap>
  </cache-template>

  <cache-template name="tinyCache">
    <heap unit="entries">20</heap>
  </cache-template>

  <cache-template name="byRefTemplate">
    <key-type copier="org.ehcache.impl.copy.IdentityCopier">java.lang.Long</key-type>
    <value-type copier="org.ehcache.impl.copy.IdentityCopier">com.pany.domain.Client</value-type>
    <heap unit="entries">10</heap>
  </cache-template>

  <cache-template name="byValueTemplate">
    <key-type copier="org.ehcache.impl.copy.SerializingCopier">java.lang.Long</key-type>
    <value-type copier="org.ehcache.impl.copy.SerializingCopier">com.pany.domain.Client</value-type>
    <heap unit="entries">10</heap>
  </cache-template>

  <cache-template name="mixedTemplate1">
    <key-type copier="org.ehcache.impl.copy.IdentityCopier">java.lang.Long</key-type>
    <value-type copier="org.ehcache.impl.copy.SerializingCopier">com.pany.domain.Client</value-type>
    <heap unit="entries">10</heap>
  </cache-template>

  <cache-template name="mixedTemplate2">
    <key-type copier="org.ehcache.impl.copy.SerializingCopier">java.lang.Long</key-type>
    <value-type copier="org.ehcache.impl.copy.IdentityCopier">com.pany.domain.Client</value-type>
    <heap unit="entries">10</heap>
  </cache-template>
</config>

(1). 首先,为JCache扩展声明一个命名空间,例如jsr107
(2). 在配置顶部的服务元素中,添加jsr107:defaults元素
(3). 元素接受一个可选属性default-template,该属性引用全部javax.cache的cache-template。使用javax.cache.CacheManager.createCache在运行时缓存应用程序建立的元素。在本例中,使用的缺省Cache -template将是tinyCache,这意味着除了它们的特定配置以外,任何经过编程建立的缓存实例的容量都将限制在20个条目。
(4). 嵌套在jsr107:defaults元素中,为给定名字的缓存添加指定的Cache -templates。例如,在运行时建立名为foos的缓存,Ehcache将加强其配置,使其容量为2000个条目,并确保键和值类型都是字符串。

使用上面的配置,您不只能够补充并且能够覆盖jcache建立的缓存的配置,而无需修改应用程序代码

MutableConfiguration<Long, Client> mutableConfiguration = new MutableConfiguration<>(); mutableConfiguration.setTypes(Long.class, Client.class); (1) Cache<Long, Client> anyCache = manager.createCache("anyCache", mutableConfiguration); (2) CacheRuntimeConfiguration<Long, Client> ehcacheConfig = (CacheRuntimeConfiguration<Long, Client>)anyCache.getConfiguration( Eh107Configuration.class).unwrap(CacheRuntimeConfiguration.class); (3) ehcacheConfig.getResourcePools().getPoolForResource(ResourceType.Core.HEAP).getSize(); (4) Cache<Long, Client> anotherCache = manager.createCache("byRefCache", mutableConfiguration); assertFalse(anotherCache.getConfiguration(Configuration.class).isStoreByValue()); (5) MutableConfiguration<String, Client> otherConfiguration = new MutableConfiguration<>(); otherConfiguration.setTypes(String.class, Client.class); otherConfiguration.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_MINUTE)); (6) Cache<String, Client> foosCache = manager.createCache("foos", otherConfiguration);(7) CacheRuntimeConfiguration<Long, Client> foosEhcacheConfig = (CacheRuntimeConfiguration<Long, Client>)foosCache.getConfiguration( Eh107Configuration.class).unwrap(CacheRuntimeConfiguration.class); Client client1 = new Client("client1", 1); foosEhcacheConfig.getExpiryPolicy().getExpiryForCreation(42L, client1).toMinutes(); (8) CompleteConfiguration<String, String> foosConfig = foosCache.getConfiguration(CompleteConfiguration.class); try { final Factory<ExpiryPolicy> expiryPolicyFactory = foosConfig.getExpiryPolicyFactory(); ExpiryPolicy expiryPolicy = expiryPolicyFactory.create(); (9) throw new AssertionError("Expected UnsupportedOperationException"); } catch (UnsupportedOperationException e) { // Expected
}

(1). 假设现有的JCache配置代码,默认状况下是按值存储的

(2). 建立JCache缓存

(3). 若是您要访问Ehcache RuntimeConfiguration

(4). 您能够验证配置的模板容量是否应用于缓存,并在这里返回20

(5). 缓存模板将覆盖JCache的按值存储配置到按引用存储,由于用于建立缓存的byRefTemplate是使用IdentityCopier显式配置的。

(6). 模板还将覆盖JCache配置,在本例中使用的配置是Time to Live (TTL) 1分钟

(7). 建立一个缓存,其中模板将TTL设置为2分钟

(8). 咱们确实能够验证模板中提供的配置是否已被应用;持续时间为2分钟,而不是1分钟

(9). 这样作的一个缺点是,当得到CompleteConfiguration时,您再也不可以从JCache访问工厂

 

五. Ehcache和经过JCache使用的Ehcache默认行为的差别

使用Ehcache和经过JCache使用的Ehcache在默认行为上并不老是一致的。虽然Ehcache能够按照JCache指定的方式运行,但这取决于使用的配置机制,您可能会看到缺省值的差别。

按引用调用或传递的

Ehcache和Ehcache经过JCache在仅支持堆缓存的默认模式上存在分歧。

使用JCache配置Ehcache

除非您调用mutableconimage.setstorebyvalue (boolean),默认值为true。这意味着在使用Ehcache时,只能使用可序列化的键和值。

这将触发使用serializing copiers ,并从默认的序列化器中选择适当的序列化器。

使用本地XML或代码配置Ehcache

Heap only: 当仅使用堆缓存时,默认值为by-reference,除非配置了Copier。

其余分层配置: 当使用任何其余层时,因为序列化起做用,默认是按值进行的。

有关信息,请参阅序列化器和复印机部分。

Cache-through和比较交换操做

Ehcache和Ehcache经过JCache对缓存加载器在比较和交换操做中的做用存在不一样

经过JCache使用Ehcache的行为

当使用比较和交换操做(如putIfAbsent(K, V))时,若是缓存没有映射,则不会使用缓存加载器。若是putIfAbsent(K, V)成功,那么缓存写入器将用于将更新传播到记录系统。这可能致使缓存的行为相似于INSERT,但实际上会致使底层记录系统的盲目更新。

使用Ehcache的行为

CacheLoaderWriter将始终用于加载缺乏的映射并写更新。这使得cache-through中的putIfAbsent(K, V)能够做为记录系统上的INSERT操做。

若是您须要经过JCache行为使用Ehcache,下面显示了相关的XML配置:

<service>
  <jsr107:defaults jsr-107-compliant-atomics="true"/>
</service>
相关文章
相关标签/搜索