Ehcache缓存框架详解

一、前言

ehcache是一个比较成熟的java缓存框架,它提供了用内存,磁盘文件存储,以及分布式存储方式等多种灵活的cache管理方案。ehcache最早从hibernate发展而来。由于3.x的版本和2.x的版本API差异比较大。这里直接学习最新版本的了,但是最后整合spring的时候还是有2.x。

二、安装

由于我的项目是使用maven管理的,因此只要在pom文件中添加如下代码即可。

<dependency>
    <groupId>javax.cachegroupId>
    <artifactId>cache-apiartifactId>
    <version>1.0.0version>
dependency>
<dependency>
    <groupId>org.ehcachegroupId>
    <artifactId>ehcacheartifactId>
    <version>3.3.1version>
dependency>

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

三、使用

1、快速入门__JAVA实现

CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() 
    .withCache("preConfigured",
        CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))) 
    .build(); 
cacheManager.init(); 

Cache preConfigured =
    cacheManager.getCache("preConfigured", Long.class, String.class); 

Cache 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.Stringkey-type>
        <value-type>java.lang.Stringvalue-type>
        
        <expiry>
            <ttl unit="seconds">2ttl>
        expiry>
        <resources>
            
            <heap unit="entries">2000heap>
            
            <offheap unit="MB">500offheap>
        resources>

    cache>
    
    <cache-template name="myDefaults">
        <key-type>java.lang.Longkey-type>
        <value-type>java.lang.Stringvalue-type>
        <heap unit="entries">200heap>
    cache-template>
    
    <cache alias="bar" uses-template="myDefaults">
        <key-type>java.lang.Numberkey-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 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文件:


<ehcache>
    
    <diskStore path="java.io.tmpdir" />

    
    <defaultCache maxElementsInMemory="10000" eternal="false"
        overflowToDisk="true" timeToIdleSeconds="10" timeToLiveSeconds="20"
        diskPersistent="false" diskExpiryThreadIntervalSeconds="120" />
    
    <cache name="cacheTest"
           maxElementsInMemory="1000"
            eternal="false"
        overflowToDisk="true" timeToIdleSeconds="10" timeToLiveSeconds="20" />

ehcache>

application.xml


<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">

    
    <context:component-scan base-package="com.lw.spring.ehcache" />

    
    <cache:annotation-driven cache-manager="ehCacheCacheManager" />

    
    <bean id="ehCacheCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager" ref="ehcache">property>
    bean>

    
    <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。上面还有几个注解,注释里也解释了。

你可能感兴趣的:(JavaEE)