过期时间 @cacheable spring boot

56

我已经实现了一个缓存,现在我想添加过期时间。

如何在Spring Boot中使用@Cacheable设置过期时间?

下面是代码片段:

@Cacheable(value="forecast",unless="#result == null")
9个回答

38

我这样使用生活技巧:

@Configuration
@EnableCaching
@EnableScheduling
public class CachingConfig {

  public static final String GAMES = "GAMES";

  @Bean
  public CacheManager cacheManager() {
    ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager(GAMES);
    return cacheManager;
  }

  @CacheEvict(allEntries = true, value = {GAMES})
  @Scheduled(fixedDelay = 10 * 60 * 1000 ,  initialDelay = 500)
  public void reportCacheEvict() {
    System.out.println("Flush Cache " + dateFormat.format(new Date()));
  }

}

23
好的,但这将会清空所有条目,无论是旧的还是新的。 - Adrian

16
请注意,本回答使用 ehcache,它是受支持的 Spring Boot 缓存管理器之一,也可以说是最流行的之一。
首先,您需要添加到pom.xml中:
<!-- Spring Framework Caching Support -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

src/main/resources/ehcache.xml文件中:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <defaultCache eternal="true" maxElementsInMemory="100" overflowToDisk="false" />
    <cache name="forecast" 
           maxElementsInMemory="1000" 
           timeToIdleSeconds="120"
           timeToLiveSeconds="120"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LRU" />
</ehcache>

1
Spring Boot没有*xml。 - nole
8
有的! :) 这是EHCache配置文件的默认位置。其他缓存库可能会指定不同的位置。 - Steve

15

来自参考文档

直接通过您的缓存提供程序进行控制。缓存抽象是一个抽象,而不是缓存实现。您使用的解决方案可能支持各种数据策略和不同的拓扑结构,而其他解决方案则不支持(例如JDK ConcurrentHashMap)-在缓存抽象中公开这些内容将是无用的,因为没有支持。这样的功能应该直接通过后备缓存进行控制,在配置时或通过其原生API进行控制。


1
谢谢。最后我已经在我的application.yml文件中添加了这个:spring.resources.cache-period。 - nole
3
抱歉,我没有看到你的例子与此有什么联系。对我来说听起来完全无关。该属性用于配置Web资源的缓存期限。 - Stephane Nicoll

11
您不能使用@cacheable注释来指定过期时间,因为@cacheable不提供此可配置选项。
但是,提供spring缓存的不同缓存供应商已通过其自己的配置提供了此功能。例如NCache/TayzGrid允许您创建具有可配置过期时间的不同缓存区域
如果您已经实现了自己的缓存,您需要定义一种方法来指定缓存提供程序中的过期时间,并且还需要在解决方案中合并过期逻辑。

9

我使用咖啡因缓存,并配置了60分钟的过期时间:

spring.cache.cache-names=forecast
spring.cache.caffeine.spec=expireAfterWrite=60m

如果我使用Caffeine Cache,如何在spring.properties中填写hibernate.cache.region.factory_class - 袁文涛
对于其他人寻找这个答案,请注意这些设置的更多信息在Spring Boot文档中。 - Garret Wilson

4

您可以通过使用@Scheduled注释来实现这种驱逐策略。可使用fixedRate或cron表达式进行调度。

@Autowired
CacheManager cacheManager;

public void evictAllCaches() {
        cacheManager.getCacheNames().stream()
          .forEach(cacheName -> cacheManager.getCache(cacheName).clear());
}

@Scheduled(fixedRate = 6000)
public void evictAllcachesAtIntervals() {
        evictAllCaches();
}

1
这应该被视为一种解决方法,因为它清除了整个缓存(与过期的概念相反,后者对于每个缓存元素都是不同的)。 - Julien Kronegg
@JulienKronegg 你可以为每个缓存单独创建这样的时间表。虽然我同意这可能不是最方便的方式。 - havryliuk

2
我找到了这篇关于Spring缓存的文章:Spring cache: Set expiry time to a cache entry。它使用了spring-boot-starter-cache依赖,并且表现正常。你可以配置缓存对象的过期时间以及最大缓存值。

1
如果您正在使用Caffeine,那么可以在application.properties文件中添加以下行:
spring.cache.caffeine.spec=expireAfterAccess=300s

如果我使用Caffeine Cache,如何在spring.properties中填写hibernate.cache.region.factory_class - 袁文涛

0
你可以使用一个 LocalDateTime 对象来解决这个问题。例如:
@Cacheable(value="forecast", key = "#date.toString()")
public void forecast(LocalDate date){
    //
}
public void call(){
    forecast(LocalDate.now());
}

缓存将在1天后过期。
积极方面-不需要预定的工作。
消极方面-旧数据仍然被缓存。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接