我正在尝试对Spring 3.1的@Cacheable
注释支持,并想知道是否有任何方法可以通过设置TTL在一段时间后清除缓存的数据?
现在从我所看到的我需要通过使用@CacheEvict
来清除它,并将其与@Scheduled
一起使用我可以自己做一个TTL实现但是对于这样的简单的任务?
答案 0 :(得分:45)
Spring 3.1和Guava 1.13.1:
@EnableCaching
@Configuration
public class CacheConfiguration implements CachingConfigurer {
@Override
public CacheManager cacheManager() {
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager() {
@Override
protected Cache createConcurrentMapCache(final String name) {
return new ConcurrentMapCache(name,
CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MINUTES).maximumSize(100).build().asMap(), false);
}
};
return cacheManager;
}
@Override
public KeyGenerator keyGenerator() {
return new DefaultKeyGenerator();
}
}
答案 1 :(得分:35)
如何设置TTL / TTI /逐出政策/ XXX功能?
直接通过缓存提供程序。缓存抽象是...... 好吧,抽象不是缓存实现
因此,如果您使用EHCache,请使用EHCache的配置来配置TTL。
您还可以使用Guava的CacheBuilder来构建缓存,并将此缓存的ConcurrentMap视图传递给setStore method of the ConcurrentMapCacheFactoryBean。
答案 2 :(得分:31)
以下是在Spring中设置Guava Cache的完整示例。我使用Guava而不是Ehcache,因为它的重量稍微轻一些,配置似乎对我来说更直接。
导入Maven依赖关系
将这些依赖项添加到maven pom文件中并运行clean和packages。这些文件是用于CacheBuilder的Guava dep和Spring辅助方法。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
配置缓存
您需要创建CacheConfig文件以使用Java配置配置缓存。
@Configuration
@EnableCaching
public class CacheConfig {
public final static String CACHE_ONE = "cacheOne";
public final static String CACHE_TWO = "cacheTwo";
@Bean
public Cache cacheOne() {
return new GuavaCache(CACHE_ONE, CacheBuilder.newBuilder()
.expireAfterWrite(60, TimeUnit.MINUTES)
.build());
}
@Bean
public Cache cacheTwo() {
return new GuavaCache(CACHE_TWO, CacheBuilder.newBuilder()
.expireAfterWrite(60, TimeUnit.SECONDS)
.build());
}
}
注释要缓存的方法
添加@Cacheable注释并传入缓存名称。
@Service
public class CachedService extends WebServiceGatewaySupport implements CachedService {
@Inject
private RestTemplate restTemplate;
@Cacheable(CacheConfig.CACHE_ONE)
public String getCached() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> reqEntity = new HttpEntity<>("url", headers);
ResponseEntity<String> response;
String url = "url";
response = restTemplate.exchange(
url,
HttpMethod.GET, reqEntity, String.class);
return response.getBody();
}
}
您可以在此处看到更完整的示例,其中带有带注释的屏幕截图:Guava Cache in Spring
答案 3 :(得分:24)
我使用像这样的生活黑客
@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()));
}
答案 4 :(得分:22)
Springboot 1.3.8
import java.util.concurrent.TimeUnit;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.common.cache.CacheBuilder;
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
@Override
@Bean
public CacheManager cacheManager() {
GuavaCacheManager cacheManager = new GuavaCacheManager();
return cacheManager;
}
@Bean
public CacheManager timeoutCacheManager() {
GuavaCacheManager cacheManager = new GuavaCacheManager();
CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterWrite(5, TimeUnit.SECONDS);
cacheManager.setCacheBuilder(cacheBuilder);
return cacheManager;
}
}
和
@Cacheable(value="A", cacheManager="timeoutCacheManager")
public Object getA(){
...
}
答案 5 :(得分:5)
这可以通过扩展org.springframework.cache.interceptor.CacheInterceptor来完成,并覆盖“doPut”方法 - org.springframework.cache.interceptor.AbstractCacheInvoker 你的覆盖逻辑应该使用缓存提供者put方法知道为缓存条目设置TTL(在我的例子中我使用HazelcastCacheManager)
@Autowired
@Qualifier(value = "cacheManager")
private CacheManager hazelcastCacheManager;
@Override
protected void doPut(Cache cache, Object key, Object result) {
//super.doPut(cache, key, result);
HazelcastCacheManager hazelcastCacheManager = (HazelcastCacheManager) this.hazelcastCacheManager;
HazelcastInstance hazelcastInstance = hazelcastCacheManager.getHazelcastInstance();
IMap<Object, Object> map = hazelcastInstance.getMap("CacheName");
//set time to leave 18000 secondes
map.put(key, result, 18000, TimeUnit.SECONDS);
}
在缓存配置中,您需要添加这两个bean方法,创建自定义拦截器实例。
@Bean
public CacheOperationSource cacheOperationSource() {
return new AnnotationCacheOperationSource();
}
@Primary
@Bean
public CacheInterceptor cacheInterceptor() {
CacheInterceptor interceptor = new MyCustomCacheInterceptor();
interceptor.setCacheOperationSources(cacheOperationSource());
return interceptor;
}
如果要在入门级别设置TTL,而不是在缓存级别设置全局,则此解决方案很好
答案 6 :(得分:2)
从Spring-boot 1.3.3开始,您可以在CacheManagerCustomizer回拨中使用 RedisCacheManager.setExpires 或 RedisCacheManager.setDefaultExpiration 在CacheManager中设置过期时间豆。
答案 7 :(得分:1)
如果您正在使用redis和Java 8,可以查看JetCache:
@Cached(expire = 10, timeUnit = TimeUnit.MINUTES)
User getUserById(long userId);
答案 8 :(得分:1)
对我来说最简单的方法是使用 Caffeine 缓存,它可以直接在您的 application.yml
文件中进行配置。
您可以通过 expireAfterWrite
参数设置 TTL。示例配置如下所示:
spring:
cache:
caffeine:
spec: expireAfterWrite=15m
cache-names: mycache
这将在 15 分钟后驱逐元素。
答案 9 :(得分:0)
使用Redis时,可以在属性文件中设置TTL,如下所示:
spring.cache.redis.time-to-live=1d # 1 day
spring.cache.redis.time-to-live=5m # 5 minutes
spring.cache.redis.time-to-live=10s # 10 seconds