美文网首页javaJava学习笔记Java 杂谈
JFinal2.2初体验之数据缓存处理(九)

JFinal2.2初体验之数据缓存处理(九)

作者: 葉糖糖 | 来源:发表于2016-10-18 15:33 被阅读1114次
    1、关于数据缓存(Cache )

    在应用程序中可使用缓存的环节是比较多的,对于如何来使用缓存,为什么要使用缓存以及生命时候使用缓存技术,有兴趣的小伙伴们可以去阅读其它大牛的技术文章或博客。我们今天只是对jfinal的数据缓存和插件使用做一个简单的科普。

    缓存的使用主要还是要根据应用的特性来考虑。首先得分析应用的“变”与“不变”,哪些地方是主要用来展示的,数据操作的不是很频繁的话,那可以使用缓存来提升应用的性能。

    EHCache 是一个纯java的在进程中的缓存,它具有以下特性:快速,简单。接下来我们一起来学习在jfinal中如何使用ehCache。

    1.1下载jfinal框架中使用到的jar包

    jar包下载地址:http://www.jfinal.com/download?file=jfinal-2.2-all.zip(需注册账号)

    序列 名称 备注
    1、 ehcache-core-2.5.2.jar 缓存核心包
    2、 slf4j-api-1.6.1.jar slf4j核心接口包
    3、 slf4j-log4j12-1.6.1.jar slf4j调用log4j的实现包
    1.2添加jar包到project(工程)

    copy文件到projectName\WebRoot\WEB-INF\lib目录下。

    1.3 添加ehcache.xml文件

    copy文件到ehcache.xml文件到project中src路径下。

    2、写一点代码使用cache
    2.1我们来为数据读取作一个简单的数据缓存操作。翠花上代码:
       /**
        * @author yetangtang
        * @see 查询用户信息
        * @param void
        * @return Page<Record> list
        */
        public Page<Record> queryUsetrList(){
            //使用Db中的paginate(分页)方法。同model操作一样
            Page<Record> list = Db.paginateByCache("userInfo", "userList", 1, 4, "select * ","from user where id > ? ",2);
            //Page<Record> list = Db.paginate(1, 4, "select * ","from user where id > ? ",2);
            //返回查询结果
            return list;
        }
    
    2.2配置ehcache.xml文件
    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="ehcache.xsd"
             updateCheck="false" monitoring="autodetect"
             dynamicConfig="true">
             
        <diskStore path="java.io.tmpdir"/>
        
            <!--
           name:缓存名称。
           maxElementsInMemory:缓存最大个数。
           eternal:对象是否永久有效,一但设置了,timeout将不起作用。
           timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
           timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
           overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
           diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
           maxElementsOnDisk:硬盘最大缓存个数。
           diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
           diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
           memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
           clearOnFlush:内存数量最大时是否清除。
        -->
         <!--默认使用的配置方式-->
        <defaultCache
               maxEntriesLocalHeap="10000"
               eternal="false"
               overflowToDisk="true"
               timeToIdleSeconds="20"
               timeToLiveSeconds="60">
        </defaultCache>
    
        <!--
        Sample cache named sampleCache1
        This cache contains a maximum in memory of 10000 elements, and will expire
        an element if it is idle for more than 5 minutes and lives for more than
        10 minutes.
    
        If there are more than 10000 elements it will overflow to the
        disk cache, which in this configuration will go to wherever java.io.tmp is
        defined on your system. On a standard Linux system this will be /tmp"
        -->
       <!--demo中使用的配置,第一种-->
        <cache name="userInfo"
               maxEntriesLocalHeap="10000"
               maxEntriesLocalDisk="1000"
               eternal="false"
               overflowToDisk="true"
               diskSpoolBufferSizeMB="20"
               timeToIdleSeconds="300"
               timeToLiveSeconds="600"
               memoryStoreEvictionPolicy="LFU"
               transactionalMode="off"
                />
                
        <!--
        Sample cache named sampleCache2
        This cache has a maximum of 1000 elements in memory. There is no overflow to disk, so 1000
        is also the maximum cache size. Note that when a cache is eternal, timeToLive and
        timeToIdle are not used and do not need to be specified.
        -->
        <!--第二种配置方式-->
        <cache name="sampleCache2"
               maxEntriesLocalHeap="1000"
               eternal="true"
               overflowToDisk="false"
               memoryStoreEvictionPolicy="FIFO"
                />
    
        <!--
        Sample cache named sampleCache3. This cache overflows to disk. The disk store is
        persistent between cache and VM restarts. The disk expiry thread interval is set to 10
        minutes, overriding the default of 2 minutes.
        -->
        <!--第三种配置方式-->
        <cache name="sampleCache3"
               maxEntriesLocalHeap="500"
               eternal="false"
               overflowToDisk="true"
               timeToIdleSeconds="300"
               timeToLiveSeconds="600"
               diskPersistent="true"
               diskExpiryThreadIntervalSeconds="1"
               memoryStoreEvictionPolicy="LFU"
                />
    </ehcache>
    
    3、探讨实现
    3.1查看方法

    Db操作类中实现了三种分页缓存方法,我们一起来看一下第一种。第一个参数是cacheName缓存名称,第二个是Object key(数据对象的名字,你可以这么理解),剩下的都比较熟悉,在此就略过。

        /**
         * Paginate by cache.
         * @see #paginate(int, int, String, String, Object...)
         * @return Page
         */
        public static Page<Record> paginateByCache(String cacheName, Object key, int pageNumber, int pageSize, String select, String sqlExceptSelect, Object... paras) {
            return dbPro.paginateByCache(cacheName, key, pageNumber, pageSize, select, sqlExceptSelect, paras);
        }
    
    3.2不知代码真面目,只缘身在代码外
        /**
         * Paginate by cache.
         * @see #paginate(int, int, String, String, Object...)
         * @return Page
         */
        public Page<Record> paginateByCache(String cacheName, Object key, int pageNumber, int pageSize, String select, String sqlExceptSelect, Object... paras) {
            //获取配置文件
            ICache cache = config.getCache();
            //尝试从缓存中获取数据对象信息
            Page<Record> result = cache.get(cacheName, key);
            //如果缓存中没有数据信息,则需要去执行查询;
            //得到查询结果后,并将数据信息添加到缓存中。
            if (result == null) {
                result = paginate(pageNumber, pageSize, select, sqlExceptSelect, paras);
                cache.put(cacheName, key, result);
            }
            return result;
        }
    
    3.3眼见为实,断点测试一下
    首次读取数据会执行

    恭喜,恭喜。至此,小伙伴们已经学会简单的使用缓存了。接下来,我们会继续玩一些好玩的技能点。

    PS:缓存虽好,依旧多结合自己系统的实际情况考虑。

    相关文章

      网友评论

      • f69335d12fbf:关于缓存这一块我有一些自己的见解来分享给大家:
        如果有一个查询出来的数据库列表(极少改动)的话,我们可以将这个列表查询出来放到缓存里面,那么会涉及到一个问题,数据的及时性就没有那么高了.我这边有个方案是,在Interceptor拦截器中拦截对该表的增删改方法(通过注解到具体方法上效率更高),拦截方法里面清空该缓存,这样就可以做到及时同步数据库和缓存的功能了.大家觉得呢
        葉糖糖:@李文文丶 嗯,看实际项目的情况吧。反正方案是基于实际情况的。你的想法确实可行。谢谢小伙伴的分享。加油,希望我们可以一起成长。
        李文文丶:我个人觉得,增加到拦截器,不如在项目中手动封装四个增删改查的工具类,所有的业务对数据的访问修改都统一走这四个工具类,然后在工具类里面,进行缓存的更新与remove,拦截器毕竟如果查多余修改,那么就拦截了不必要的请求,我是这么理解的。
        葉糖糖:这也不失为一种好方法。很不错的做法,欢迎继续交流。:+1:

      本文标题:JFinal2.2初体验之数据缓存处理(九)

      本文链接:https://www.haomeiwen.com/subject/fcttuttx.html