我有一个简单的Grails应用程序,需要在用户会话期间(使用界面时)多次定期调用外部Web服务。
我想缓存此Web服务响应,但服务的结果每隔几天就会发生变化,所以我想将其缓存一小段时间(也许每天刷新)。
Grails缓存插件似乎不支持“生存时间”实现,所以我一直在探索一些可能的解决方案。我想知道什么插件或程序解决方案最能解决这个问题。
示例:
BuildConfig.groovy
plugins{
compile ':cache:1.0.0'
}
MyController.groovy
def getItems(){
def items = MyService.getItems()
[items: items]
}
MyService.groovy
@Cacheable("itemsCache")
class MyService {
def getItems() {
def results
//expensive external web service call
return results
}
}
更新
有很多不错的选择。我决定采用Burt建议的插件方法。我已经包含了一个示例答案,对上面的代码示例进行了微小的更改,以帮助其他人想要做类似的事情。此配置在24小时后使缓存失效。
BuildConfig.groovy
plugins{
compile ':cache:1.1.7'
compile ':cache-ehcache:1.0.1'
}
Config.groovy中
grails.cache.config = {
defaultCache {
maxElementsInMemory 10000
eternal false
timeToIdleSeconds 86400
timeToLiveSeconds 86400
overflowToDisk false
maxElementsOnDisk 0
diskPersistent false
diskExpiryThreadIntervalSeconds 120
memoryStoreEvictionPolicy 'LRU'
}
}
答案 0 :(得分:12)
核心插件不支持TTL,但Ehcache插件支持TTL。见http://grails-plugins.github.com/grails-cache-ehcache/docs/manual/guide/usage.html#dsl
http://grails.org/plugin/cache-ehcache插件取决于http://grails.org/plugin/cache,但将缓存管理器替换为使用Ehcache的缓存管理器(因此您需要同时安装)
答案 1 :(得分:1)
黑客/解决方法是使用@Cacheable(“itemsCache”)和@CacheFlush(“itemsCache”)的组合。
告诉getItems()方法缓存结果。
@Cacheable("itemsCache")
def getItems() {
}
然后使用另一种刷新缓存的服务方法,您可以从作业中频繁调用。
@CacheFlush("itemsCache")
def flushItemsCache() {}
答案 2 :(得分:0)
从grails-cache单元测试(查找timeToLiveSeconds),我看到您可以在缓存级别配置缓存,而不是按方法调用或类似方式。使用此方法,您可以配置 grails.cache.config 。
的设置您可以使用生存时间设置创建专用缓存,然后在您的服务中引用它。
答案 3 :(得分:0)
在与SpEL的战斗中失败几个小时后,我最终赢得了战争! 因此,您知道Grails缓存没有开箱即用的TTL。您可以坚持使用ehcache并进行一些奇特的配置。或者更糟糕的是添加逻辑在保存/更新等时刷新它。但我的解决方案是:
@Cacheable(value = 'domainInstance', key="#someId.concat((new java.util.GregorianCalendar().getTimeInMillis()/10000))")
def getSomeStuffOfDb(String someId){
//extract something of db
}
}
还有一点需要指出。您可以在Config.groovy中跳过配置,它将自动创建和添加。 但是,如果您的应用在启动后直接加载,则会导致一些例外情况。
2017-03-02 14:05:53,159 [http-apr-8080-exec-169] ERROR errors.GrailsExceptionResolver - CacheException occurred when processing request: [GET] /some/get
Failed to get lock for campaignInstance cache creation. Stacktrace follows:
所以为了避免这种情况,请添加配置,以便事先准备好缓存设施。
grails.cache.enabled = true
grails.cache.clearAtStartup = true
grails.cache.config = {
defaults {
maxElementsInMemory 10000
overflowToDisk false
}
cache {
name 'domainInstance'
}
}
GregorianCalendar()。getTimeInMillis()/ 10000将使TTL~10秒。 / 1000~1秒。纯数学在这里。