博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
初识EHCache缓存框架(2.x版本)
阅读量:6968 次
发布时间:2019-06-27

本文共 15002 字,大约阅读时间需要 50 分钟。

hot3.png

官方文档:

参考文档:

关于EHCache3.x版本的使用详见此篇博客:

Maven依赖:

net.sf.ehcache
ehcache
2.10.3

1.独立使用

在class根目录下加入配置文件ehcache1.xml.

Java代码如下:

public static void main(String[] args) {        // Create a cache manager        final CacheManager cacheManager = CacheManager.newInstance(EHCacheTest.class                .getResource("/ehcache1.xml"));        // create the cache called "hello-world"        final Cache cache = cacheManager.getCache("hello-world1");        // create a key to map the data to        final String key = "greeting";        // Create a data element        final Element putGreeting = new Element(key, "Hello, World!");        // Put the element into the data store        cache.put(putGreeting);        // Retrieve the data element        final Element getGreeting = cache.get(key);        // Print the value        System.out.println(getGreeting.getObjectValue());    }

输出结果如下(包括日志):

DEBUG 18:15:24,365 [main](ConfigurationFactory.java:98) - Configuring ehcache from URL: file:/D:/WORKSPACE/intelljIdea/SSMProjectMaven/target/test-classes/ehcache1.xmlDEBUG 18:15:24,371 [main](ConfigurationFactory.java:150) - Configuring ehcache from InputStreamDEBUG 18:15:24,466 [main](BeanHandler.java:271) - Ignoring ehcache attribute xmlns:xsiDEBUG 18:15:24,466 [main](BeanHandler.java:271) - Ignoring ehcache attribute xsi:noNamespaceSchemaLocationDEBUG 18:15:24,474 [main](DiskStoreConfiguration.java:141) - Disk Store Path: C:\Users\FlyingHe\AppData\Local\Temp\/ehcacheDEBUG 18:15:24,526 [main](CacheManager.java:1102) - Creating new CacheManager with config URL: file:/D:/WORKSPACE/intelljIdea/SSMProjectMaven/target/test-classes/ehcache1.xmlDEBUG 18:15:24,531 [main](PropertyUtil.java:87) - propertiesString is null.DEBUG 18:15:24,553 [main](ConfigurationHelper.java:189) - No CacheManagerEventListenerFactory class specified. Skipping...DEBUG 18:15:25,168 [main](Cache.java:1044) - No BootstrapCacheLoaderFactory class specified. Skipping...DEBUG 18:15:25,169 [main](Cache.java:1017) - CacheWriter factory not configured. Skipping...DEBUG 18:15:25,169 [main](ConfigurationHelper.java:100) - No CacheExceptionHandlerFactory class specified. Skipping...DEBUG 18:15:25,189 [main](Cache.java:1044) - No BootstrapCacheLoaderFactory class specified. Skipping...DEBUG 18:15:25,189 [main](Cache.java:1017) - CacheWriter factory not configured. Skipping...DEBUG 18:15:25,190 [main](ConfigurationHelper.java:100) - No CacheExceptionHandlerFactory class specified. Skipping...DEBUG 18:15:25,243 [main](MemoryStore.java:180) - Initialized net.sf.ehcache.store.MemoryStore for hello-world1DEBUG 18:15:25,406 [main](ExtendedStatisticsImpl.java:224) - Mocking Pass-Through Statistic: LOCAL_OFFHEAP_SIZEDEBUG 18:15:25,414 [main](ExtendedStatisticsImpl.java:224) - Mocking Pass-Through Statistic: LOCAL_OFFHEAP_SIZE_BYTESDEBUG 18:15:25,415 [main](ExtendedStatisticsImpl.java:224) - Mocking Pass-Through Statistic: LOCAL_DISK_SIZEDEBUG 18:15:25,416 [main](ExtendedStatisticsImpl.java:224) - Mocking Pass-Through Statistic: LOCAL_DISK_SIZE_BYTESDEBUG 18:15:25,417 [main](ExtendedStatisticsImpl.java:224) - Mocking Pass-Through Statistic: WRITER_QUEUE_LENGTHDEBUG 18:15:25,419 [main](ExtendedStatisticsImpl.java:224) - Mocking Pass-Through Statistic: REMOTE_SIZEDEBUG 18:15:25,419 [main](ExtendedStatisticsImpl.java:224) - Mocking Pass-Through Statistic: LAST_REJOIN_TIMESTAMPDEBUG 18:15:25,516 [main](ExtendedStatisticsImpl.java:206) - Mocking Operation Statistic: OFFHEAP_GETDEBUG 18:15:25,518 [main](ExtendedStatisticsImpl.java:206) - Mocking Operation Statistic: OFFHEAP_PUTDEBUG 18:15:25,519 [main](ExtendedStatisticsImpl.java:206) - Mocking Operation Statistic: OFFHEAP_REMOVEDEBUG 18:15:25,522 [main](ExtendedStatisticsImpl.java:206) - Mocking Operation Statistic: DISK_GETDEBUG 18:15:25,523 [main](ExtendedStatisticsImpl.java:206) - Mocking Operation Statistic: DISK_PUTDEBUG 18:15:25,524 [main](ExtendedStatisticsImpl.java:206) - Mocking Operation Statistic: DISK_REMOVEDEBUG 18:15:25,525 [main](ExtendedStatisticsImpl.java:206) - Mocking Operation Statistic: XA_COMMITDEBUG 18:15:25,526 [main](ExtendedStatisticsImpl.java:206) - Mocking Operation Statistic: XA_ROLLBACKDEBUG 18:15:25,556 [main](ExtendedStatisticsImpl.java:206) - Mocking Operation Statistic: XA_RECOVERYDEBUG 18:15:25,565 [main](ExtendedStatisticsImpl.java:206) - Mocking Operation Statistic: CLUSTER_EVENTDEBUG 18:15:25,566 [main](ExtendedStatisticsImpl.java:206) - Mocking Operation Statistic: NONSTOPDEBUG 18:15:25,578 [main](Cache.java:1262) - Initialised cache: hello-world1DEBUG 18:15:25,578 [main](ConfigurationHelper.java:334) - CacheDecoratorFactory not configured. Skipping for 'hello-world1'.DEBUG 18:15:25,578 [main](ConfigurationHelper.java:364) - CacheDecoratorFactory not configured for defaultCache. Skipping for 'hello-world1'.Hello, World!

注:

如果在实例化CacheManager时采用此种方式CacheManager manager = CacheManager.newInstance();则默认加载class根目录下的ehcache.xml文件。

在官方文档中已给出多种加载配置文件的方式的解释:

地址:

182136_3vvv_2608182.png

关于更多配置文件的解释:

对于配置文件:

解释如下:

1、diskStore :指定数据(.data and .index)存储位置,可指定磁盘中的文件夹位置期 The diskStore element is optional. It must be configured if you have overflowToDisk or diskPersistent enabled    for any cache. If it is not configured, a warning will be issues and java.io.tmpdir will be used.2、defaultCache : 默认的管理策略一、以下属性是必须的:  1、name: Cache的名称,必须是唯一的(ehcache会把这个cache放到HashMap里)。  2、maxElementsInMemory:在内存中缓存的element的最大数目。   3、maxElementsOnDisk:在磁盘上缓存的element的最大数目,默认值为0,表示不限制。   4、eternal:设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断。   5、overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上。 二、以下属性是可选的:  1、timeToIdleSeconds: 对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问。  2、timeToLiveSeconds: 对象存活时间,指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问。  3、diskPersistent: 是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false。   4、diskExpiryThreadIntervalSeconds: 对象检测线程运行时间间隔。标识对象状态的线程多长时间运行一次。  5、diskSpoolBufferSizeMB: DiskStore使用的磁盘大小,默认值30MB。每个cache使用各自的DiskStore。   6、memoryStoreEvictionPolicy: 如果内存中数据超过内存限制,向磁盘缓存时的策略。默认值LRU,可选FIFO、LFU。 四、缓存的3 种清空策略 :  1、FIFO ,first in first out (先进先出).  2、LFU , Less Frequently Used (最少使用).意思是一直以来最少被使用的。缓存的元素有一个hit 属性,hit 值最小的将会被清出缓存。  3、LRU ,Least Recently Used(最近最少使用). (ehcache 默认值).缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。

2.EHCache2.x版本与Spring的整合使用

引入Spring相关的包这里不再详述。

①创建一个ehcache-spring.xml的文件,配置Spring

②创建ehcache1.xml文件,配置EHCache

③创建一个Person类,需要缓存的对象的所属类必须实现java.io.Serializable接口

package at.flying.domain;import java.io.Serializable;public class Person implements Serializable {    private static final long serialVersionUID = 1L;    private int id;    private String name;    public Person() {}    public Person(int id, String name) {        this.id = id;        this.name = name;    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public String toString() {        return "id=" + this.id + ", name=" + this.name;    }}

④创建一个PersonService类,用于模拟对数据库操作的业务逻辑

package at.flying.service;import at.flying.domain.Person;import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.springframework.stereotype.Service;import java.util.HashSet;import java.util.Set;public class PersonService {    private Set
people; public PersonService() { people = new HashSet<>(); Person person1 = new Person(1, "张三"); Person person2 = new Person(2, "赵四"); Person person3 = new Person(3, "王五"); people.add(person1); people.add(person2); people.add(person3); } @Cacheable({"Person"}) public Person findUser(Person person) { return findUserInDB(person.getId()); } @Cacheable(value = "Person", condition = "#person.getId() <= 2") public Person findUserInLimit(Person person) { return findUserInDB(person.getId()); } @CachePut(value = "Person") public Person updateUser(Person person) { updateUserInDB(person); return person; } @CacheEvict(value = "Person") public void removeUser(Person person) { removeUserInDB(person.getId()); } @CacheEvict(value = "Person", allEntries = true) public void clear() { removeAllInDB(); } /** * 模拟查找数据库 */ private Person findUserInDB(int id) { for (Person u : people) { if (id == u.getId()) { System.out.println("查找数据库 id = " + id + " 成功"); return u; } } return null; } /** * 模拟更新数据库 */ private void updateUserInDB(Person person) { for (Person u : people) { if (person.getId() == u.getId()) { System.out.println("更新数据库" + u + " -> " + person); u.setName(person.getName()); } } } private void removeUserInDB(int id) { for (Person u : people) { if (id == u.getId()) { System.out.println("从数据库移除 id = " + id + " 的数据"); people.remove(u); break; } } } private void removeAllInDB() { people.clear(); }}

⑤测试类EHCacheSpringTest

package at.flying.test;import at.flying.domain.Person;import at.flying.service.PersonService;import net.sf.ehcache.Element;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.ehcache.EhCacheCacheManager;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.util.List;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"classpath:at/flying/ehcache/spring/xml/ehcache-spring.xml"})public class EHCacheSpringTest {    @Autowired    PersonService personService;    @Autowired    EhCacheCacheManager cacheManager;    /**     * 测试@Cacheable     */    @Test    public void testFindUser() throws InterruptedException {        // 设置查询条件        Person person1 = new Person(1, null);        Person person2 = new Person(2, null);        Person person3 = new Person(3, null);        System.out.println("第一次查询");        System.out.println(personService.findUser(person1));        System.out.println(personService.findUser(person2));        System.out.println(personService.findUser(person3));        this.printCacheStatus();        System.out.println("\n第二次查询");        System.out.println(personService.findUser(person1));        System.out.println(personService.findUser(person2));        System.out.println(personService.findUser(person3));        // 在classpath:ehcache/ehcache.xml中,设置了userCache的缓存时间为3000 ms, 这里设置等待        Thread.sleep(3000);        System.out.println("\n缓存过期,再次查询");        System.out.println(personService.findUser(person1));        System.out.println(personService.findUser(person2));        System.out.println(personService.findUser(person3));    }    /**     * 输出当前Person缓存的缓存信息     */    public void printCacheStatus() {        net.sf.ehcache.CacheManager cacheManager = this.cacheManager.getCacheManager();        net.sf.ehcache.Cache cache = cacheManager.getCache("Person");        System.out.println("缓存对象数:" + cache.getSize());        System.out.println("各元素的Key-Value如下:");        List keys = cache.getKeys();        for (Object o : keys) {            Element e = cache.get(o);            System.out.println(o + " -> " + e.getObjectValue());        }    }    /**     * 测试@Cacheable设置Spring SpEL条件限制     */    @Test    public void testFindUserInLimit() throws InterruptedException {        // 设置查询条件        Person person1 = new Person(1, null);        Person person2 = new Person(2, null);        Person person3 = new Person(3, null);        System.out.println("第一次查询user info");        System.out.println(personService.findUserInLimit(person1));        System.out.println(personService.findUserInLimit(person2));        System.out.println(personService.findUserInLimit(person3));        System.out.println("\n第二次查询user info");        System.out.println(personService.findUserInLimit(person1));        System.out.println(personService.findUserInLimit(person2));        System.out.println(personService.findUserInLimit(person3)); // 超过限制条件,不会从缓存中读数据        // 在classpath:ehcache/ehcache.xml中,设置了userCache的缓存时间为3000 ms, 这里设置等待        Thread.sleep(3000);        System.out.println("\n缓存过期,再次查询");        System.out.println(personService.findUserInLimit(person1));        System.out.println(personService.findUserInLimit(person2));        System.out.println(personService.findUserInLimit(person3));    }    /**     * 测试@CachePut     */    @Test    public void testUpdateUser() {        // 设置查询条件        Person person2 = new Person(2, null);        System.out.println(personService.findUser(person2));        this.printCacheStatus();        personService.updateUser(new Person(2, "尼古拉斯.赵四"));        this.printCacheStatus();        System.out.println(personService.findUser(person2));    }    /**     * 测试@CacheEvict删除指定缓存     */    @Test    public void testRemoveUser() {        // 设置查询条件        Person person1 = new Person(1, null);        System.out.println("数据删除前:");        System.out.println(personService.findUser(person1));        personService.removeUser(person1);        System.out.println("数据删除后:");        System.out.println(personService.findUser(person1));    }    /**     * 测试@CacheEvict删除所有缓存     */    @Test    public void testClear() {        System.out.println("数据清空前:");        System.out.println(personService.findUser(new Person(1, null)));        System.out.println(personService.findUser(new Person(2, null)));        System.out.println(personService.findUser(new Person(3, null)));        personService.clear();        System.out.println("\n数据清空后:");        System.out.println(personService.findUser(new Person(1, null)));        System.out.println(personService.findUser(new Person(2, null)));        System.out.println(personService.findUser(new Person(3, null)));    }}

测试结果不再贴出。

注意:

注解Cacheable与Cacheput的区别:

cacheable一般用于查询数据,cacheput一般用于修改数据。两者都会对修饰的方法的返回值做缓存,如果在注解中没有指定缓存时的key并且也没有指定keyGenerator参数的话,那么默认key将会是直接调用缓存对象的toString()方法的返回值作为key,如果被修饰的方法没有返回值,那么缓存值value将会是null

并且对于Cacheable如果在查询时发现缓存中存在,则不再执行被修饰的方法体,也就是说不会取数据库中查询数据,而对于CachePut的话,不管怎样被修饰的方法体都会执行,所以说,Cacheable一般用于查询数据,而CachePut一般用于修改数据。

结果可测试得到,这里不再贴出测试结果。

关于这三个注解的详细解释可以参考此篇博客:

关于EHCache配置文件中diskStore的解释可参看此篇博客:

转载于:https://my.oschina.net/u/2608182/blog/890916

你可能感兴趣的文章
js 获取窗口、屏幕、页面元素宽高+位置(兼容ie)
查看>>
[Webpack并不难]使用教程(三)--- plugins
查看>>
TOP100summit:【分享实录】链家网大数据平台体系构建历程
查看>>
2017-10-13 前端日报
查看>>
PHP-X 系列教程:扩展内定义类和对象
查看>>
面试--css实现元素的水平和垂直居中
查看>>
软键盘管理
查看>>
vuex的简单介绍
查看>>
ES2015入门系列1-初识ES2015
查看>>
Python: 链式赋值的坑
查看>>
【收藏】8段JQuery处理表单的代码片段,很实用
查看>>
利用 Css 制作精美的卡片UI
查看>>
7步学会在Windows下上架iOS APP流程
查看>>
nodejs源码中的require问题
查看>>
带标签的长标题省略展示的实现
查看>>
WordPress.com使用JavaScript替换掉PHP
查看>>
linux基础命令介绍七:网络传输与安全
查看>>
nginx 负载均衡搭建
查看>>
[vue+vuex+vue-router] 强撸一发暗黑风 markdown 日记应用
查看>>
分布式文件系统 go-fastdfs v1.2.7 发布,增加 Nginx 配置模版
查看>>