我可以为@Cacheable设置TTL吗?
我正在尝试Spring 3.1的@Cacheable批注支持,并想知道是否有任何方法可以通过设置一个TTL使caching的数据清除一段时间? 现在我可以看到,我需要使用@CacheEvict自己清除它,通过和@Scheduled一起使用,我可以自己做一个TTL实现,但对于这样一个简单的任务似乎有点多?
如何设置TTL / TTI /驱逐策略/ XXXfunction?
直接通过您的caching提供商。 caching抽象是…好吧,抽象不是caching实现
因此,如果您使用EHCache,请使用EHCache的configuration来configurationTTL。
您也可以使用Guava的CacheBuilder构build一个caching,并将该caching的ConcurrentMap视图传递给ConcurrentMapCacheFactoryBean的setStore方法 。
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(); } }
下面是在Spring中设置Guava Cache的完整示例。 我在Ehcache上使用番石榴,因为它的重量更轻一点,configuration看起来更直接。
导入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>
configurationcaching
您需要创build一个CacheConfig文件来使用Javaconfiguration来configurationcaching。
@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()); } }
注释要caching的方法
添加@Cacheable注释并传入caching名称。
@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(); } }
你可以在这里看到一个更完整的例子,带有注解的截图: Spring中的Guava Cache
我用这样的生活黑客
@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())); }
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(){ ... }
这可以通过扩展org.springframework.cache.interceptor.CacheInterceptor,并重写“doPut”方法来完成 – org.springframework.cache.interceptor.AbstractCacheInvoker你的覆盖逻辑应该使用caching提供者的put方法知道为caching条目设置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); }
在你的cachingconfiguration上,你需要添加这两个bean方法,创build你的自定义拦截器实例。
@Bean public CacheOperationSource cacheOperationSource() { return new AnnotationCacheOperationSource(); } @Primary @Bean public CacheInterceptor cacheInterceptor() { CacheInterceptor interceptor = new MyCustomCacheInterceptor(); interceptor.setCacheOperationSources(cacheOperationSource()); return interceptor; }
如果您想在入门级设置TTL,而不是在caching级全局设置,则此解决scheme非常有用
您可以使用RedisCacheManager.setExpires或RedisCacheManager.setDefaultExpiration在CacheManager中设置实时时间