grails中的cache

来源:互联网 发布:淘宝衣服模特 编辑:程序博客网 时间:2024/06/07 22:23

最近在做grails的项目中用到了缓存,遇到了一些问题,在这里记录一下啊。

首先,创建的grails工程默认会带有cache plugin。我用的是grails2.1.1,新建工程后会带一个插件:cache 1.0.0。这个插件是Spring提供的。具体如何使用在这http://grails-plugins.github.io/grails-cache/docs/manual/guide/introduction.html。这个插件的作者是Jeff Brown和Burt Beckwith

另外,Burt Beckwith还对cache 1.0.0进行了扩展,使用ehcache作为缓存的提供者。ehcache的使用和cahche plugin基本相同,具体请看这里:http://grails-plugins.github.io/grails-cache-ehcache/docs/manual/guide/introduction.html。

而我在做项目时,开始并没有注意这两个插件。而是自己引入ehcache的jar包来实现的。开始时我这样做的,遇到了一些问题:

1、grails2.1.1项目本身带有ehcache-core-2.4.6.jar,无需自己再引入。

2、复制配置文件ehcache.xml和ehcache.xsd。第一次我复制到了conf目录下

ehcache.xml中配置了一个cahche:

<cache name="advertisementCache"
        maxElementsInMemory="100"
        eternal="true"
        overflowToDisk="false"
        memoryStoreEvictionPolicy="LRU" />

3、在conf/spring/resource.groovy中配置缓存bean

beans = {
    //----------------------EhCache配置---------------------------begin
    //EhCacheManagerFactoryBean创建的cacheManager是单例模式的
    cacheManager (EhCacheManagerFactoryBean){bean->
        shared=true
    }//EhCacheManagerFactoryBean是一个FactoryBean,用来产生CacheManager
    advertismentCache(EhCacheFactoryBean){//EhCacheFactoryBean是一个FactoryBean,用来产生Cache
        cacheManager = ref("cacheManager")
        cacheName = "advertisementCache"
    }
    clientVersionCache(EhCacheFactoryBean){//EhCacheFactoryBean是一个FactoryBean,用来产生Cache
        cacheManager = ref("cacheManager")
        cacheName = "clientVersionCache"
    }
    //---------------------EhCache配置---------------------------end
}
可以看到我对advertisementCache中的eternal设为true,即缓存中的元素用不过期。

可程序跑起来后,在执行下边的代码时出现了问题:

advertismentCache.keys.each {
                Element element=advertismentCache.get(it)
                if(element){
                    Advertisement advertisement=element.getObjectValue()
                    if(advertisement.photoStudioCode.equals(photoStudioCode)){
                        results.add(advertisement)
                    }
                }
            }

advertismentCache在程序启动时会存入一组数据。在程序启动后的一段时间里,上边的代码正常。一段时间后,advertismentCache.keys中有值,但进入循环Element element=advertismentCache.get(it)获取的element为null。再次执行代码,advertismentCache.keys中也没有了数据。

仔细查看ehcache的文档,得到了解释advertismentCache.keys获取的是缓存中所有的key,而不管这个元素没有过期(expired)。缓存中可能存在过期的元素。当遇到这种元素时,advertismentCache.get(it)返回的是null。同时会把过期的元素从缓存中清理掉。所有再次调用代码,advertismentCache.keys中也没有了数据。

那么看来是缓存中的数据过期了。可是我设置了eternal="true",数据应该永不过期才对。为啥没起作用?

继续google,在EhCacheManagerFactoryBean的源代码中看到了这样一段注释:

Set the location of the EHCache config file. A typical value is "/WEB-INF/ehcache.xml".

Default is "ehcache.xml" in the root of the class path, or if not found, "ehcache-failsafe.xml" in the EHCache jar (default EHCache initialization).

看来是ehcache.xml位置没有放对,默认使用了ehcache-failsafe.xml。后来的测试验证了我的猜想。于是我把ehcache.xml挪到了/web-app/WEB-INF下。同时修改resource.groovy,如下:

//EhCacheManagerFactoryBean创建的cacheManager是单例模式的
    cacheManager (EhCacheManagerFactoryBean){bean->
        shared=true
        configLocation="/WEB-INF/ehcache.xml"
    }//EhCacheManagerFactoryBean是一个FactoryBean,用来产生CacheManager
    advertismentCache(EhCacheFactoryBean){//EhCacheFactoryBean是一个FactoryBean,用来产生Cache
        cacheManager = ref("cacheManager")
        cacheName = "advertisementCache"
    }
    clientVersionCache(EhCacheFactoryBean){//EhCacheFactoryBean是一个FactoryBean,用来产生Cache
        cacheManager = ref("cacheManager")
        cacheName = "clientVersionCache"
    }

再次运行一切正常。之所以没方队class path下,是因为grails工程中,往classpath下放不太好放。没去研究。有知道的可以告诉我!

(PS:写的挺简单有条理,可这个问题整整折腾了我1天半。做程序员,如何准确的定位问题,是个难题啊)

1 0
原创粉丝点击