Я пробую @Cacheable
поддержку аннотаций для Spring 3.1 и задаюсь вопросом, есть ли способ очистить кешированные данные через некоторое время, установив TTL? Прямо сейчас из того, что я вижу, мне нужно очистить это сам, используя @CacheEvict
, и, используя это вместе с, @Scheduled
я могу сам сделать реализацию TTL, но это кажется многовато для такой простой задачи?
108
Вот полный пример настройки Guava Cache весной. Я использовал Guava вместо Ehcache, потому что он немного легче и конфигурация мне показалась более простой.
Импортировать зависимости Maven
Добавьте эти зависимости в свой файл maven pom и запустите clean и packages. Эти файлы являются вспомогательными методами Guava dep и Spring для использования в CacheBuilder.
<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
источник
Я использую лайфхаки вот так
@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())); }
источник
reportCacheEvict
метод из любого места. Как происходит cacheEvict ??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, ваша логика переопределения должна использовать метод 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); }
в вашей конфигурации кеша вам нужно добавить эти 2 метода bean, создав свой собственный экземпляр перехватчика.
@Bean public CacheOperationSource cacheOperationSource() { return new AnnotationCacheOperationSource(); } @Primary @Bean public CacheInterceptor cacheInterceptor() { CacheInterceptor interceptor = new MyCustomCacheInterceptor(); interceptor.setCacheOperationSources(cacheOperationSource()); return interceptor; }
Это решение хорошо, если вы хотите установить TTL на начальном уровне, а не глобально на уровне кеша.
источник
Начиная с Spring-boot 1.3.3, вы можете установить время истечения срока действия в CacheManager, используя RedisCacheManager.setExpires или RedisCacheManager.setDefaultExpiration в компоненте обратного вызова CacheManagerCustomizer .
источник
При использовании 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
источник
Если вы работаете с Redis и Java 8, вы можете взглянуть на JetCache :
@Cached(expire = 10, timeUnit = TimeUnit.MINUTES) User getUserById(long userId);
источник