Ehcache简介

Ehcache是一个纯Java的进程内缓存框架,是Hibernate中默认的CacheProvider,主要面向通用缓存,Java EE和轻量级容器。主要特性有:

  1. 简单快速
  2. 多种缓存策略,支持LRU、LFU和FIFO。
  3. 支持内存和硬盘作为缓存存储
  4. 缓存数据会在虚拟机重启的过程中写入磁盘
  5. 具有缓存和缓存管理器的侦听接口
  6. 可以通过RMI、可插入API等方式进行分布式缓存
  7. 可与spring、Hibernate、shiro等框架组件进行整合

项目中Ehcache的配置

Jeesite中Ehcache的配置文件主要在资源目录下的cache文件夹中,默认使用的是ehcache-local.xmlehcahce-hibernate-xml,前者是ehcache的配置文件,后者是针对hibernate的配置文件。下面先看一下ehcache-local.xml的内容:

<ehcache updateCheck="false" name="defaultCache">

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

<!-- DefaultCache setting. -->
<defaultCache maxEntriesLocalHeap="100" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600"
    overflowToDisk="true" maxEntriesLocalDisk="100000" />

<cache name="sysCache" maxElementsInMemory="100" eternal="true" overflowToDisk="true"/>

<cache name="cmsCache" maxElementsInMemory="100" eternal="true" overflowToDisk="true"/>
    
<cache name="shiro-activeSessionCache" maxElementsInMemory="100" overflowToDisk="true"
       eternal="true" timeToLiveSeconds="0" timeToIdleSeconds="0"
       diskPersistent="true" diskExpiryThreadIntervalSeconds="600"/>

<cache name="org.apache.shiro.realm.text.PropertiesRealm-0-accounts"
       maxElementsInMemory="100" eternal="true" overflowToDisk="true"/>

<cache name="SimplePageCachingFilter" maxElementsInMemory="100" eternal="false" overflowToDisk="true"
    timeToIdleSeconds="120" timeToLiveSeconds="120" memoryStoreEvictionPolicy="LFU"/>
    
</ehcache>

其中,syscache和cmscache分别是针对系统管理模块和内容管理模块的缓存。SimplePageCachingFilter是页面缓存。各缓存项的含义如下:

  • diskStore path: 缓存保存到磁盘的位置
  • maxElementsInMemory:缓存中允许创建的最大对象数
  • eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。
  • timeToIdleSeconds:缓存数据的钝化时间,也就是在一个元素消亡之前,两次访问时间的最大时间间隔值,这只能在元素不是永久驻留时有效。
  • timeToLiveSeconds:缓存数据的生存时间,也就是一个元素从构建到消亡的最大时间间隔值,这只能在元素不是永久驻留时有效。
  • overflowToDisk:内存不足时,是否启用磁盘缓存。

ehcahce-hibernate-xml则是针对sys模块中的实体类通过hibernate来缓存,包括User、Role、Menu、Office、Area、Dict以及userList、MenuList、roleList等实体类。下面列举几个配置,其他的以此类推:

<cache name="com.thinkgem.jeesite.modules.sys.entity.Area" maxEntriesLocalHeap="100" eternal="false" overflowToDisk="true" maxEntriesLocalDisk="100000" />
<cache name="com.thinkgem.jeesite.modules.sys.entity.Area.childList" maxEntriesLocalHeap="100" eternal="false" overflowToDisk="true" maxEntriesLocalDisk="100000" />
<cache name="com.thinkgem.jeesite.modules.sys.entity.Area.officeList" maxEntriesLocalHeap="100" eternal="false" overflowToDisk="true" maxEntriesLocalDisk="100000" />

对于页面缓存来说,还要在Servlet容器的web.xml这个配置文件中配置:

<!-- Ehcache 页面缓存,仅缓存首页和html为后缀的页面 (需要时取消注释)
<filter>  
<filter-name>PageCacheFilter</filter-name>  
    <filter-class>com.thinkgem.jeesite.common.filter.PageCachingFilter  
</filter-class>
</filter>

<filter-mapping>  
    <filter-name>PageCacheFilter</filter-name>
    <url-pattern>/</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>PageCacheFilter</filter-name>
    <url-pattern>*.html</url-pattern>
</filter-mapping>-->

这里只针对站点首页和html静态页面做了缓存,对应的缓存类是common.filter包下的PageCacheingFilter类。下面就看一下项目中的缓存工具类

项目中的ehcache缓存代码。

首先要针对页面缓存作一下说明,页面缓存主要用Filter过滤器对请求的url进行过滤,如果该url在缓存中出现。那么页面数据就从缓存对象中获取,并以gzip压缩后返回。其速度是没有压缩缓存时速度的3-5倍,效率相当之高!其中页面缓存的过滤器有CachingFilter,一般要扩展filter或是自定义Filter都继承该CachingFilter。CachingFilter功能可以对HTTP响应的内容进行缓存。这种方式缓存数据的粒度比较粗,例如缓存整张页面。EHCache使用SimplePageCachingFilter类实现Filter缓存。现在看一下Jeesite中的Filter:

public class PageCachingFilter extends SimplePageCachingFilter {

    @Override
    protected CacheManager getCacheManager() {
        return CacheUtils.getCacheManager();
    }   
}

这里的页面缓存过滤器继承了ehcache提供的SimplePageCachingFilter,通过自己写的缓存工具类CacheUtils来获得缓存管理器CacheManager,下面先介绍Ehcache的基本用法,然后对应分析一下CacheUtils类:

//获取缓存管理器
CacheManager cacheManager = CacheManager.create();
cacheManager = CacheManager.getInstance();
cacheManager = CacheManager.newInstance("/config/ehcache.xml");
//通过缓存管理器获取ehcache配置文件中的一个cache
Cache sample = cacheManager.getCache("sample");
//添加数据到缓存中
Element element = new Element("key", "val");
sample.put(element);
//获取缓存中的对象,注意添加到cache中对象要序列化 实现Serializable接口
Element result = sample.get("key");
// 删除缓存
sample.remove("key");
sample.removeAll();

CahceUtils类就是对这些Ehcache的基本缓存操作做了封装:

public class CacheUtils {
//通过Spring来获取缓存管理器
private static CacheManager cacheManager = ((CacheManager)SpringContextHolder.getBean("cacheManager"));
    //对应ehcache-local.xml配置的系统模块缓存
private static final String SYS_CACHE = "sysCache";
    //以下是针对系统模块缓存的操作
public static Object get(String key) {
    return get(SYS_CACHE, key);
}
public static void put(String key, Object value) {
    put(SYS_CACHE, key, value);
}
public static void remove(String key) {
    remove(SYS_CACHE, key);
}
//封装Ehcache的get put remove操作
public static Object get(String cacheName, String key) {
    Element element = getCache(cacheName).get(key);
    return element==null?null:element.getObjectValue();
}

public static void put(String cacheName, String key, Object value) {
    Element element = new Element(key, value);
    getCache(cacheName).put(element);
}

public static void remove(String cacheName, String key) {
    getCache(cacheName).remove(key);
}

/**
 * 获得一个Cache,没有则创建一个。
 * @param cacheName
 * @return
 */
private static Cache getCache(String cacheName){
    Cache cache = cacheManager.getCache(cacheName);
    if (cache == null){
        cacheManager.addCache(cacheName);
        cache = cacheManager.getCache(cacheName);
        cache.getCacheConfiguration().setEternal(true);
    }
    return cache;
}

public static CacheManager getCacheManager() {
    return cacheManager;
}   
}