我有一个Spring Boot / MVC应用程序,应该存储用户发送的一些简单POJO 15分钟。当此时间到期时,应从ConcurrentHashMap
中删除此对象。起初ConcurrentHashMap
是我想要实现此功能的东西,但后来我认为可能利用Guava的缓存是一个更好的选择,因为它有一个开箱即用的基于时间的驱逐。
我的服务实施
@CachePut(cacheNames = "teamConfigs", key = "#authAccessDto.accessToken")
@Override
public OAuthAccessDto saveConfig(OAuthAccessDto authAccessDto) {
return authAccessDto;
}
@Override
@Cacheable(cacheNames = "teamConfigs")
public OAuthAccessDto getConfig(String accessToken) {
// we assume that the cache is already populated
return null;
}
如您所见,我们使用saveConfig
保存数据,然后当我们需要检索数据时,我们会调用getConfig
。
Spring引导中的缓存配置如下(yml文件):
spring:
cache:
cache-names: teamConfigs
guava:
spec: expireAfterWrites=900s
然而,在阅读了Guava的缓存文档https://github.com/google/guava/wiki/CachesExplained之后,我发现Guava可以在 {{1}中定义的时间之前清除缓存过去(甚至在内存不足之前)。
如何配置Guava Cache以保持对象直到时间到期(认为它没有耗尽内存)。也许我应该选择其他解决方案?
答案 0 :(得分:2)
我不了解Guava,但你可以使用任何符合JSR-107标准的提供商和一个看起来像这样的简单配置:
@Bean
public JCacheManagerCustomizer cacheManagerCustomizer() {
return cm -> {
cm.createCache("teamConfigs", new MutableConfiguration<>()
.setExpiryPolicyFactory(CreatedExpiryPolicy
.factoryOf(new Duration(MINUTES, 15)));
};
}
Caffeine(用Java8重写Guava)有一个JSR-107提供程序,所以你可以使用它。也许那个版本没有展示你对番石榴的体验?如果是这样,预计Spring Boot 1.4中会提供支持,但您现在可以尝试JSR-107支持。
如果您不想使用它,可以尝试expiringmap。它在Spring抽象中没有任何Cache
实现,但由于它是Map
,你可以很容易地将它包装起来,就像在我的头顶上一样:
@Bean
public Cache teamConfigsCache() {
Map<Object, Object> map = ExpiringMap.builder()
.expiration(15, TimeUnit.MINUTES)
.build();
return new ConcurrentMapCache("teamConfigs", map , true);
}
如果Spring Boot在配置中发现至少Cache
个bean,it auto-creates a CacheManager
implementation that wraps them。您可以通过the spring.cache.type
property强制执行该行为。