一. 概述JCache

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

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

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

二. 使用Ehcache为JCache提供实现

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

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

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

三. 开始使用Ehcache和JCache

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

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

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>

Ehcache 3.7文档—基础篇—JCache aka JSR-107的更多相关文章

  1. Ehcache 3.7文档—基础篇—XML Configuration

    你可以使用xml配置创建CacheManager,根据这个schema definition ( http://www.ehcache.org/documentation/3.7/xsds.html# ...

  2. Ehcache 3.7文档—基础篇—Tiering Options

    Ehcache支持分层缓存的概念,这节主要介绍不同的配置选项,同时也解释了规则和最佳实践. 一. 数据缓存到堆外 当在cache中除了有heap层之外,有一些需要注意的: 添加一个key-value到 ...

  3. Ehcache 3.7文档—基础篇—GettingStarted

    为了使用Ehcache,你需要配置CacheManager和Cache,有两种方式可以配置java编程配置或者XML文件配置 一. 通过java编程配置 CacheManager cacheManag ...

  4. Mongoose学习参考文档——基础篇

    Mongoose学习参考文档 前言:本学习参考文档仅供参考,如有问题,师请雅正 一.快速通道 1.1 名词解释 Schema : 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力 Model ...

  5. XWPFDocument创建和读取Office Word文档基础篇(一)

    注:有不正确的地方还望大神能够指出,抱拳了 老铁!   参考API:http://poi.apache.org/apidocs/org/apache/poi/xwpf/usermodel/XWPFDo ...

  6. java 使用 POI 操作 XWPFDocumen 创建和读取 Office Word 文档基础篇

    注:有不正确的地方还望大神能够指出,抱拳了 老铁! 参考 API:http://poi.apache.org/apidocs/org/apache/poi/xwpf/usermodel/XWPFDoc ...

  7. TypeScript学习文档-基础篇(完结)

    目录 TypeScript学习第一章:TypeScript初识 1.1 TypeScript学习初见 1.2 TypeScript介绍 1.3 JS .TS 和 ES之间的关系 1.4 TS的竞争者有 ...

  8. HTML文档基础

    一.HTML(Hyper Text Markup Language超文本标记语言)是一种用来制作超文本文档的简单标记语言,HTML在正文的文本中编写各种标记,通过Web浏览器进行编译和运行才干正确显示 ...

  9. Excelize 发布 2.6.0 版本,功能强大的 Excel 文档基础库

    Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准.可以使用它来读取.写入由 Microsoft Exc ...

随机推荐

  1. 408 JavaScript 变量、数据类型、正则

    JavaScript 特点 是一门解释性脚本语言 .基于对象脚本编程.简单性(弱类型).安全性.动态性.跨平台 作用: 初学js 引入方式 与html有相同之处 也是3种1 用JavaScript前缀 ...

  2. html 超链接标签 锚点 a标签伪类

    一个简易的连接 <a href="01.html">01</a> <body> <a href="01.html" t ...

  3. CEC和ARC介绍

    众所周知,HDMI作为一个数字化视频音频的接收标准,是可以同时传输视频和音频的,当然随着HDMI版本的提升,它的功能也一直在增强.事实上 当HDMI升级到1.3时,人们就发现了HDMI多了一个CEC功 ...

  4. 【easy】110. Balanced Binary Tree判断二叉树是否平衡

    判断二叉树是否平衡 a height-balanced binary tree is defined as a binary tree in which the depth of the two su ...

  5. STM32F0使用LL库实现MS5536C通讯

    在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片.这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现.在本文中我们说明一下,使用LL库实现MS5 ...

  6. python 学习第四天

    2.5列表list. 列表是python中的基础数据类型之一,其他语言中也有类似于列表的数据类型,比如js中叫数组,他是以[]括起来,每个元素以逗号隔开,而且他里面可以存放各种数据类型比如: li = ...

  7. VIM编辑常用命令

    1.临时使用获取root权限保存文件 :w !sudo tee % 2.多标签编辑文件 :tabnew file 3.切换标签 :tabm N   (N为第几个标签,从0开始)

  8. TortoiseGit安装使用简单教程

    一.简介 TortoiseGit是Tortoise基于git的可视化管理工具.本文即将介绍这个工具的安装和简单使用教程(本文均是基于Windows 64位操作系统). git的管理工具有很多.Tort ...

  9. SpringBoot之hello world!

    哈哈哈,还是在元旦这一天对你下手了.麻溜的给自己充电,在这个寒冬,不断听到裁员的消息或者新闻,可对于我这个外包和外派的人来说,好像并没有受到什么影响.可能是人手不够可能是项目很忙.对于明年的三月金四月 ...

  10. ExtJS5搭建MVVM框架

    概述 · ExtJs5能够搭建Js的MVC框架,通过配置路由能够通过左边树形菜单导航到所需的页面,效果如下: 搭建JS框架 新建home.htm页面作为ExtJs加载的主体页面,页面引入ExtJs需要 ...