zoukankan      html  css  js  c++  java
  • Ehcache缓存框架具体解释

    一、前言

    ehcache是一个比較成熟的java缓存框架。它提供了用内存,磁盘文件存储。以及分布式存储方式等多种灵活的cache管理方案。ehcache最早从hibernate发展而来。

    因为3.x的版本号和2.x的版本号API差异比較大。这里直接学习最新版本号的了,可是最后整合spring的时候还是有2.x。

    二、安装

    因为我的项目是使用maven管理的,因此仅仅要在pom文件里加入例如以下代码就可以。

    <dependency>
        <groupId>javax.cache</groupId>
        <artifactId>cache-api</artifactId>
        <version>1.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.ehcache</groupId>
        <artifactId>ehcache</artifactId>
        <version>3.3.1</version>
    </dependency>

    好像ehcache还要依赖上面的那个Cache,因此最好两个多加上。

    三、使用

    1、高速入门__JAVA实现

    CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() 
        .withCache("preConfigured",
            CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))) 
        .build(); 
    cacheManager.init(); 
    
    Cache<Long, String> preConfigured =
        cacheManager.getCache("preConfigured", Long.class, String.class); 
    
    Cache<Long, String> myCache = cacheManager.createCache("myCache", 
        CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)));
    
    myCache.put(1L, "da one!"); 
    String value = myCache.get(1L); 
    
    cacheManager.removeCache("preConfigured"); 
    
    cacheManager.close(); 

    这里使用的官网的样例。

    • CacheManagerBuilder.newCacheManagerBuilder():创建缓存构造器的构建者,相似工厂模式,注意,里面的实现不是单例。
    • .withCache() :相当于创建一个自带缓存的CacheManager。
    • build() :这种方法就是创建CacheManager了。

      上面的build方法接受一个boolean參数:当为true时。CacheManager在使用时就不用初始化,否则,就须要CacheManager调用init()进行初始化操作。

      默觉得false。

    • cacheManager.getCache():获取缓存

    • cacheManager.createCache():创建缓存。
    • myCache.put(1L, “da one!”):在缓存中加入值

    2、高速入门__XML实现

        <cache alias="foo">
            <!-- 缓存键值对的类型 -->
            <key-type>java.lang.String</key-type>
            <value-type>java.lang.String</value-type>
            <!-- 配置缓存 -->
            <expiry>
                <ttl unit="seconds">2</ttl>
            </expiry>
            <resources>
                <!-- 在堆中申请2000个entries -->
                <heap unit="entries">2000</heap>
                <!-- 最大非堆内存 -->
                <offheap unit="MB">500</offheap>
            </resources>
    
        </cache>
        <!-- 定一个模板 -->
        <cache-template name="myDefaults">
            <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">
            <key-type>java.lang.Number</key-type>
        </cache>
    
        <cache alias="simpleCache" uses-template="myDefaults" />
    // 測试xml
        @Test
        public void test03() {
            URL url = getClass().getResource("/ehcache.xml");
            XmlConfiguration conf = new XmlConfiguration(url);
            CacheManager cacheManager = CacheManagerBuilder.newCacheManager(conf);
            cacheManager.init();
            Cache<String, String> cache = cacheManager.getCache("foo", String.class, String.class);
            cache.put("key", "value");
            try {
                Thread.sleep(1000); // 測试过期时间
                String value = cache.get("key");
                System.out.println("result:" + value);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    

    上面即演示了xml实现缓存,凝视都比較清楚了。之所以在java中调用Thread.sleep(1000)。就是为了測试在xml中设置过期时间是否有效。

    三、磁盘缓存

    PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                    .with(CacheManagerBuilder.persistence(new File("myData")))
                    .withCache("threeTieredCache",
                            CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
                                    ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES)
                                            .offheap(1, MemoryUnit.MB).disk(20, MemoryUnit.MB, true)))
                    .build(true);
    
            Cache<Long, String> threeTieredCache = persistentCacheManager.getCache("threeTieredCache", Long.class,
                    String.class);
            threeTieredCache.put(1L, "stillAvailableAfterRestart");
    
            persistentCacheManager.close();

    上面代码即会在当前项目的同级文件夹下创建一个mydata文件夹。

    四、Spring和Ehcache整合

    Spring本身并没有提供缓存的功能,可是却对市面上好多缓存框架提供了支持,即也支持Ehcache。

    因为Spring4好像对ehcache3.x不是太支持。因此这里选用2.x。

    ehcache.xml文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache>
        <!-- 指定一个文件文件夹。当EhCache把数据写到硬盘上时。将把数据写到这个文件文件夹下 -->
        <diskStore path="java.io.tmpdir" />
    
        <!-- 设定缓存的默认数据过期策略 -->
        <defaultCache maxElementsInMemory="10000" eternal="false"
            overflowToDisk="true" timeToIdleSeconds="10" timeToLiveSeconds="20"
            diskPersistent="false" diskExpiryThreadIntervalSeconds="120" />
        <!-- 
            name:缓存名称
    
            maxElementsInMemory:内存中最大缓存对象数
    
            maxElementsOnDisk:硬盘中最大缓存对象数。若是0表示无穷大
    
            eternal:true表示对象永只是期,此时会忽略timeToIdleSeconds和timeToLiveSeconds属性,默觉得false
    
            overflowToDisk:true表示当内存缓存的对象数目达到了
    
            maxElementsInMemory界限后,会把溢出的对象写到硬盘缓存中。注意:假设缓存的对象要写入到硬盘中的话。则该对象必须实现了Serializable接口才行。
    
            diskSpoolBufferSizeMB:磁盘缓存区大小,默觉得30MB。

    每一个Cache都应该有自己的一个缓存区。 diskPersistent:是否缓存虚拟机重新启动期数据,是否持久化磁盘缓存,当这个属性的值为true时,系统在初始化时会在磁盘中查找文件名称 为cache名称,后缀名为index的文件。这个文件里存放了已经持久化在磁盘中的cache的index,找到后会把cache载入到内存,要想把 cache真正持久化到磁盘,敲代码时注意运行net.sf.ehcache.Cache.put(Element element)后要调用flush()方法。 diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔。默觉得120秒 timeToIdleSeconds: 设定同意对象处于空暇状态的最长时间,以秒为单位。

    当对象自从近期一次被訪问后。假设处于空暇状态的时间超过了timeToIdleSeconds属性 值,这个对象就会过期,EHCache将把它从缓存中清空。

    仅仅有当eternal属性为false。该属性才有效。假设该属性值为0,则表示对象能够无限 期地处于空暇状态 timeToLiveSeconds:设定对象同意存在于缓存中的最长时间,以秒为单位。当对象自从被存放到缓存中后。假设处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期。EHCache将把它从缓存中清除。

    仅仅有当eternal属性为false,该属性才有 效。

    假设该属性值为0。则表示对象能够无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性,才有 意义 memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会依据指定的策略去清理内存。可选策略有:LRU(近期最少使用。默认策略)、FIFO(先进先出)、LFU(最少訪问次数)。 --> <cache name="cacheTest" maxElementsInMemory="1000" eternal="false" overflowToDisk="true" timeToIdleSeconds="10" timeToLiveSeconds="20" /> </ehcache>

    application.xml

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

    > <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd"> <!-- 自己主动扫描注解的bean --> <context:component-scan base-package="com.lw.spring.ehcache" /> <!-- 注解扫描 --> <cache:annotation-driven cache-manager="ehCacheCacheManager" /> <!-- 实例CacheManager --> <bean id="ehCacheCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheManager" ref="ehcache"></property> </bean> <!-- 载入ehcache配置文件 --> <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation" value="classpath:ehcache.xml"></property> </bean> </beans>

    创建一个service接口,并加入实现。

    package com.lw.spring.ehcache;
    
    import org.springframework.cache.annotation.CachePut;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.stereotype.Service;
    
    @Service
    public class EhcacheServiceImpl implements EhcacheService {
    
        /**
         * @Cacheable
         * 表明所修饰的方法是能够缓存的:当第一次调用这种方法时,
         * 它的结果会被缓存下来,在缓存的有效时间内。

    假设每次缓存返回的结果都是一样的。则不会运行方法体的代码 * 以后訪问这种方法都直接返回缓存结果,不再运行方法中的代码段。

    * @CachePut:功能比@Cacheable更强。不仅缓存方法结果,还缓存代码段,每次都会运行方法体的内容 * @CacheEvict:功能和@Cacheable功能相反,@CacheEvict表明所修饰的方法是用来删除失效或没用的缓存数据。 * @CacheConfig:与前面的缓存注解不同。这是一个类级别的注解。假设类的全部操作都是缓存操作。你能够使用@CacheConfig来指定类,省去一些配置。 * condition:缓存的条件。能够为null,使用spel编写,仅仅有返回true的情况下才进行缓存 * 这种方法会以key中的值作为缓存中的key,返回结果作为缓存中的值进行缓存 */ @CachePut(value = "cacheTest", key = "#param",condition="1<2") public String getTime(String param) { System.out.println("getTime方法调用了..."); Long time = System.currentTimeMillis(); return time.toString(); } }

    測试:

    package com.lw.spring.ehcache;
    
    import org.junit.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
    
    @ContextConfiguration(locations={"classpath:application.xml"})
    public class EhcacheTest  extends AbstractJUnit4SpringContextTests{
    
        @Autowired  
        private EhcacheService ehcacheService;
    
        @Test  
        public void getTimestampTest() throws InterruptedException{  
            System.out.println("第一次调用:" + ehcacheService.getTime("param"));
    
            System.out.println("调用:" + ehcacheService.getTime("param"));
    
            System.out.println("调用:" + ehcacheService.getTime("param"));
    
            System.out.println("调用:" + ehcacheService.getTime("param"));
    
            System.out.println("调用:" + ehcacheService.getTime("param"));
    
            System.out.println("调用:" + ehcacheService.getTime("param"));
    
            System.out.println("调用:" + ehcacheService.getTime("param"));
            Thread.sleep(11000);// 10s之后缓存消失
            System.out.println("再过11秒之后调用:" + ehcacheService.getTime("param"));
        } 
    }
    
    

    上面就完毕了Spring和ehcache的结合了。

    事实上主要就是ehcache的核心类交给了Spring。上面还有几个注解,凝视里也解释了。

  • 相关阅读:
    [NOI2004] 郁闷的出纳员
    对象内部套嵌多个对象
    函数
    匿名函数、对象
    函数部分
    Html部分
    搜索二叉树的应用
    二叉树的线索化
    搜索结构搜索二叉树
    堆与最优级队列
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/7288860.html
Copyright © 2011-2022 走看看