我正在使用Spring Boot和EhCache开发日历应用程序。
有些用户可以申请特定周的音乐会,其他用户可以申请整个月。所有响应都被缓存,生存时间为300秒,以减少响应时间。
缓存方法的输入参数为startDate
,endDate
和username
。
问题是当用户请求整个月的音乐会,然后在同一个月内的一个星期,该方法将被执行两次,即使“周”响应可以基于“月”计算响应,因为本周可能是缓存月份的一部分。
示例:
1.
INPUT
startDate:08.06.2016, endDate:07.07.2016, username:exampleUser
//the method is executed, response cached
OUTPUT
concert "Example Concert" on 13.06.2016
2
INPUT
startDate:08.06.2016, endDate:15.06.2016, username:exampleUser
//the method is executed, response cached
OUTPUT
concert "Example Concert" on 13.06.2016
正如您在示例中所看到的,该方法将被执行两次,但实际上没有必要在第二个示例中执行该方法,可以从第一个请求中返回的缓存数据中提取响应。
我正在考虑为concerts
缓存创建一个自定义“生成器”,它可以遍历所有缓存的数据,并查找“包含”请求startDate
和endDate
的日期范围
这是我到目前为止所做的:
缓存方法:
@Override
@CachePut("concerts")
public List<Event> refreshEventsCache(String eventsForUser, Date startDate, Date endDate) throws Exception {
return fetchEventsFromTheServer(eventsForUser, startDate, endDate);
}
@Override
@Cacheable(value = "concerts")
public List<Event> getEvents(String eventsForUser, Date startDate, Date endDate) throws Exception {
return fetchEventsFromTheServer(eventsForUser, startDate, endDate);
}
ehcache.xml中:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<defaultCache maxElementsInMemory="500" eternal="false"
overflowToDisk="false" memoryStoreEvictionPolicy="LFU" />
<diskStore path="java.io.tempdir"/>
<cache name="concerts"
maxElementsInMemory="5000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="300"
overflowToDisk="false"
memoryStoreEvictionPolicy="LFU" />
</ehcache>
Application.java:
...
@SpringBootApplication
@ComponentScan
@EnableCaching
@EnableScheduling
public class SpringBootWebApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SpringBootWebApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<SpringBootWebApplication> applicationClass = SpringBootWebApplication.class;
}
如何构建“智能”缓存生成器,它将返回缓存数据的子集?
答案 0 :(得分:1)
您无法在此处使用Spring的默认缓存机制,因为在以下方法中,
@Override
@Cacheable(value = "concerts")
public List<Event> getEvents(String eventsForUser, Date startDate, Date endDate) throws Exception {
return fetchEventsFromTheServer(eventsForUser, startDate, endDate);
}
将根据所有三个参数eventsForUser, startDate, endDate
生成缓存密钥。
因此,在您的第二个查询中,即前一个startDate
和endDate
之间的一周,生成的密钥将会有所不同,因此会有一个缓存未命中,因此它将直接从数据库加载。< / p>
根据您的要求,您需要实施一个&#34; Smart&#34;为此缓存只是一个想法,
您可以注入CacheManager
并使用它根据您生成的缓存密钥检索缓存列表。
Ex: - startDate的缓存键:08.06.2016,endDate:07.07.2016,用户名:exampleUser可以是08.06.2016_07.07.2016_exampleUser
。
您可以使用
Cache cache = cacheManager.getCache("08.06.2016_15.06.2016_exampleUser");
如果缓存未命中,请尝试首先获取Week的缓存,然后您可以转到endDate
月份的最后一个日期并检查Month的缓存
Cache cache = cacheManager.getCache("08.06.2016_07.07.2016_exampleUser");
如果你找到了月份的缓存,你可以迭代从中获取周的缓存,或者你必须从数据库中获取周的缓存。