Могу ли я установить TTL для @Cacheable
Я пробую @Cacheable
поддержка аннотаций для Spring 3.1 и интересно, есть ли способ очистить кэшированные данные через некоторое время, установив TTL?
Прямо сейчас из того, что я вижу, мне нужно очистить его самостоятельно с помощью @CacheEvict
, и используя это вместе с @Scheduled
Я могу сделать реализацию TTL сам, но это кажется немного много для такой простой задачи?
8 ответов:
Как я могу установить функцию TTL/TTI / Eviction policy / XXX?
непосредственно через поставщика кэша. Абстракция кэша есть... ну, абстракция не реализация кэша
Итак, если вы используете EHCache, используйте конфигурацию EHCache для настройки ТТЛ.
вы также можете использовать Guava CacheBuilder чтобы построить кэш и передать представление ConcurrentMap этого кэша в setStore метод ConcurrentMapCacheFactoryBean.
Весна 3.1 и гуава 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(); } }
вот полный пример настройки кэша Guava весной. Я использовал Guava над Ehcache, потому что он немного легче, и конфигурация казалась мне более прямой.
Импорт Зависимостей Maven
добавьте эти зависимости в файл maven pom и запустите clean and packages. Эти файлы являются Guava dep и Spring helper методы для использования в 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 config.
@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(); } }
вы можете увидеть более полный пример здесь с аннотированные скриншоты: гуава кэш весной
Я использую лайфхак вот так
@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(){ ... }
Это можно сделать путем расширения организации.springframework.кэш.перехватчик.CacheInterceptor, и переопределить метод "doPut" - org.springframework.кэш.перехватчик.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 call-back bean.
Если вы работаете с redis и Java 8, вы можете взглянуть на JetCache:
@Cached(expire = 10, timeUnit = TimeUnit.MINUTES) User getUserById(long userId);