Jfinal中使用EhCache缓存

来源:互联网 发布:linux查看telnet服务 编辑:程序博客网 时间:2024/04/28 12:30

1、前言

Ehcache是一个快速的、轻量级的、易于使用的、进程内的缓存。它支持read-only和read/write 缓存,内存和磁盘缓存。是一个非常轻量级的缓存实现,而且从1.2之后就支持了集群。

简单地说来,ehcache有以下特点:

  • 快速、简单.
  • 多种缓存策略
  • 缓存数据有两级:内存和磁盘,因此无需担心容量问题
  • 缓存数据会在虚拟机重启的过程中写入磁盘
  • 可以通过RMI、可插入API 等方式进行分布式缓存
  • 具有缓存和缓存管理器的侦听接口
  • 支持多缓存管理器实例,以及一个实例的多个缓存区域
  • 提供Hibernate的缓存实现

具体ehcache配置和使用可参考我另一篇博客:ehcache的使用
这里重点说明,ehcache在JJfinal中的使用


2、Jfinal中使用ehcache

2.1、引入jar包

项目中想使用ehcache缓存,首先需要引入对应jar,Jfinal项目也不例外,但无需在ehcache官网下载,Jfinal文件中就有相应jar包,以“Jfinal-3.0”为了,在Jfinal官网上下载“jfinal-3.0-all.zip”压缩包,并解压:
这里写图片描述

解压完成后,依次进入目录“jfinal-3.0-all”->“jfinal-3.0-lib”->“ehcache”,其中“jfinal-3.0-lib”文件夹存放着Jfinal需要的全部jar包,也包含ehcache的jar包
这里写图片描述
“ehcache”文件夹中有以上三个jar包和一个标准的ehcache配置文件;将以上三个jar包都引入项目,并将配置文件“ehcache.xml”放在“src”或“res”目录下
这里写图片描述


2.2、在项目中配置EhCache

JFinal 已经集成了ehcache缓存,以plugin形式存在,叫“EhCachePlugin”。需要在项目的DemoConfig.java中配置后才能使用:

public class DemoConfig extends JFinalConfig {    /**     * 配置插件     */    public void configPlugin(Plugins me) {        URL url = getClass().getResource("res/ehcache.xml");                me.add(new EhCachePlugin(url));    }}   

2.3、EhCachePlugin

com.jfinal.plugin.ehcache.EhCachePlugin继承了 com.jfinal.plugin.IPlugin
接口;在EhCachePlugin中主要是生成cacheManager,并将cacheManager放在CacheKit 中:
1、在EhCachePlugin中有多个构造函数,都是传递不同类型的ehcache配置文件参数或直接传递CacheManager ,供后面使用(上例中使用了URL形式的参数)

public class EhCachePlugin implements IPlugin {    private static CacheManager cacheManager;    private String configurationFileName;    private URL configurationFileURL;    private InputStream inputStream;    private Configuration configuration;    public EhCachePlugin() {        }    public EhCachePlugin(CacheManager cacheManager) {        EhCachePlugin.cacheManager = cacheManager;    }    public EhCachePlugin(String configurationFileName) {        this.configurationFileName = configurationFileName;     }    public EhCachePlugin(URL configurationFileURL) {        this.configurationFileURL = configurationFileURL;    }    public EhCachePlugin(InputStream inputStream) {        this.inputStream = inputStream;    }    public EhCachePlugin(Configuration configuration) {        this.configuration = configuration;    }}   

2、每个Plugin都会有start方法,在项目启动时执行。 EhCachePlugin 在start方法中调用createCacheManager()方法,创建CacheManager;并将CacheManager放在CacheKit中【CacheKit.init(cacheManager)】,供项目使用

    public boolean start() {        createCacheManager();        CacheKit.init(cacheManager);        return true;    }    private void createCacheManager() {        if (cacheManager != null)            return ;        if (configurationFileName != null) {            cacheManager = CacheManager.create(configurationFileName);            return ;        }        if (configurationFileURL != null) {            cacheManager = CacheManager.create(configurationFileURL);            return ;        }        if (inputStream != null) {            cacheManager = CacheManager.create(inputStream);            return ;        }        if (configuration != null) {            cacheManager = CacheManager.create(configuration);            return ;        }               cacheManager = CacheManager.create();    }

2.4、CacheKit

com.jfinal.plugin.ehcache.CacheKit是ehcache缓存的操作工具类,在EhCachePlugin中,已经将cacheManager放在CacheKit 中(给CacheKit的cacheManager参数赋值),所以可以在项目中通过CacheKit,来使用ehcache缓存技术

    public void index() {        int pageNumber = getParaToInt(0, 1);        Page<Blog> blogPage = CacheKit.get("blogTest", "blogList");        if(blogPage == null){            blogPage = Blog.me.paginate(pageNumber, 10);            CacheKit.put("blogTest", "blogList",blogPage);        }           setAttr("blogPage",blogPage);        render("blog.html");    }

CacheKit 中最重要的两个方法是get(String cacheName, Objectkey)put(String cacheName,Object key, Object value)。get 方法是从cache中取数据,put方法是将数据放入cache。参数cacheName与ehcache.xml中的<cache name="blogTest" …>name属性值对应; 参数key是指取值用到的key;参数 value 是被缓存的数据。对应上例的ehcache.xml配置如下:

    <cache name="blogTest"           maxEntriesLocalHeap="10000"           maxEntriesLocalDisk="1000"           eternal="false"            diskSpoolBufferSizeMB="30"           timeToIdleSeconds="0"           timeToLiveSeconds="0"           memoryStoreEvictionPolicy="LRU">        <persistence strategy="localTempSwap"/>    </cache>

ehcache.xml的配置在此不做展开说明,详见我的另一片文章

除了以上介绍的get(String cacheName, Objectkey)方法外,CacheKit还提供了CacheKit.get(String, String, IDataLoader)方法,使用方式如下:

public void index() {    Page<Blog> blogPage = CacheKit.get("blogTest", "blogList", new IDataLoader(){            public Object load(){                return Blog.me.paginate(getParaToInt(0, 1), 10);            }        });         setAttr("blogPage",blogPage);        render("blog.html");    }

CacheKit.get方法提供了一个IDataLoader接口,该接口中的load()方法在缓存值不存在时才会被调用。该方法的具体操作流程是:首先以 cacheName=blogTest 以及 key=blogList 为参数去缓存取数据,如果缓存中数据存在就直接返回该数据,不存在则调用 IDataLoader.load()方法来获取数据,并将获取到的数据通过put(cacheName, key, data)放在cache中。


CacheKit中的其他方法:


  • List getKeys(String cacheName):获取名称为“cacheName”的cache中全部key。
  • remove(String cacheName, Object key):删除某一缓存
  • removeAll(String cacheName):删除cache中的全部缓存
  • static Cache getOrAddCache(String cacheName):根据cacheName获取或创建cache。

getOrAddCache方法是put、get方法的基础。
如果ehcache.xml中未配置以cacheName命名的cache,getOrAddCache方法会调用cacheManager.addCacheIfAbsent(cacheName)创建cache,缓存策略使用default

2.5、CacheInterceptor

除了工具类外,还可以通过配置拦截器的方式使用ehcache缓存。
CacheInterceptor可以将 action 所需数据全部缓存起来,下次请求到来时如果cache存在则直接使用数据并render,而不会去调用action。此用法可使 action 完全不受 cache 相关代码所污染,即插即用,以下是示例代码:

    @Before(CacheInterceptor.class)    public void index() {        int pageNumber = getParaToInt(0, 1);        Page<Blog> blogPage = Blog.me.paginate(pageNumber, 10);        setAttr("blogPage", blogPage);        render("blog.html");    }

运行结果如下,可以看出第二次执行,没有打印sql,意味着没有查询数据库,直接从缓存中取值:
这里写图片描述

上例中的用法将使用 actionKey作为cacheName(使用具体的url(actionKey+参数)作为cacheKey),在使用之前需要在 ehcache.xml中配置以actionKey命名的cache 如:<cache name="/blog" …>,注意 actionKey 作为cacheName配置时斜杠”/”不能省略(如果没有在ehcache.xml配置对应的cache,系统会使用default,详见CacheKit的getOrAddCache方法)。此外CacheInterceptor 还可以与CacheName注解配合使用,以此来取代默认的 actionKey 作为 cacheName,以下是示例代码:

    @Before(CacheInterceptor.class)    @CacheName("bloglist")    public void index() {        int pageNumber = getParaToInt(0, 1);        Page<Blog> blogPage = Blog.me.paginate(pageNumber, 10);        setAttr("blogPage", blogPage);        render("blog.html");    }

以上用法需要在ehcache.xml中配置名为bloglist的cache如:<cache name="bloglist" …>


2.6、EvictInterceptor

EvictInterceptor 可以根据 CacheName 注解自动清除缓存。以下是示例代码:

    @Before(EvictInterceptor.class)    @CacheName("bloglist")    public void delete() {        Blog.me.deleteById(getParaToInt());        redirect("/blog");    }

上例中的用法将清除 cacheName 为 blogList 的缓存数据,与其配合的CacheInterceptor 会自动更新 cacheName 为 blogList 的缓存数据。

查看以下EvictInterceptor源代码可以看到,在执行完inv.invoke()后,调用CacheKit.removeAll(buildCacheName(inv))方法,将名为cacheName的缓存全部清除。

public class EvictInterceptor implements Interceptor{    final public void intercept(Invocation inv) {        inv.invoke();           CacheKit.removeAll(buildCacheName(inv));    }}

参考:《Jfinal用户手册》
Jfinal官网:http://www.jfinal.com/

0 0
原创粉丝点击