Spring Cache - 生成自定义缓存结果

时间:2016-06-08 17:48:19

标签: java spring spring-boot ehcache spring-cache

我正在使用Spring Boot和EhCache开发日历应用程序。

有些用户可以申请特定周的音乐会,其他用户可以申请整个月。所有响应都被缓存,生存时间为300秒,以减少响应时间。

缓存方法的输入参数为startDateendDateusername

问题是当用户请求整个月的音乐会,然后在同一个月内的一个星期,该方法将被执行两次,即使“周”响应可以基于“月”计算响应,因为本周可能是缓存月份的一部分。

示例:

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缓存创建一个自定义“生成器”,它可以遍历所有缓存的数据,并查找“包含”请求startDateendDate的日期范围

这是我到目前为止所做的:

缓存方法:

@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;



}

如何构建“智能”缓存生成器,它将返回缓存数据的子集?

1 个答案:

答案 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生成缓存密钥。

因此,在您的第二个查询中,即前一个startDateendDate之间的一周,生成的密钥将会有所不同,因此会有一个缓存未命中,因此它将直接从数据库加载。< / 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");

如果你找到了月份的缓存,你可以迭代从中获取周的缓存,或者你必须从数据库中获取周的缓存。