Staram się o @Cacheable
wsparcie dla adnotacji wiosny 3.1 i zastanawiasz się, czy jest jakiś sposób, aby dane w pamięci podręcznej usunąć po pewnym czasie przez ustawienie TTL? W tej chwili z tego, co widzę, muszę sam to wyczyścić za pomocą @CacheEvict
, a używając tego razem z @Scheduled
mogę samodzielnie wykonać implementację TTL, ale wydaje się, że to trochę za dużo jak na tak proste zadanie?
106
Oto pełny przykład konfiguracji Guava Cache na wiosnę. Użyłem guawy zamiast Ehcache, ponieważ jest nieco lżejszy, a konfiguracja wydawała mi się prostsza.
Importuj zależności Maven
Dodaj te zależności do pliku pom maven i uruchom czyste i pakiety. Te pliki są metodami pomocniczymi Guava dep i Spring do użycia w 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>
Skonfiguruj pamięć podręczną
Musisz utworzyć plik CacheConfig, aby skonfigurować pamięć podręczną przy użyciu konfiguracji 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()); } }
Opisz metodę, która ma być buforowana
Dodaj adnotację @Cacheable i podaj nazwę pamięci podręcznej.
@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(); } }
Możesz zobaczyć bardziej kompletny przykład tutaj z opisami zrzutów ekranu: Guava Cache in Spring
źródło
Używam hakowania życia w ten sposób
@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())); }
źródło
reportCacheEvict
metodę z dowolnego miejsca. Jak dzieje się 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; } }
i
@Cacheable(value="A", cacheManager="timeoutCacheManager") public Object getA(){ ... }
źródło
można to zrobić rozszerzając org.springframework.cache.interceptor.CacheInterceptor i zastępując metodę „doPut” - org.springframework.cache.interceptor.AbstractCacheInvoker Twoja logika override powinna używać metody put dostawcy pamięci podręcznej, która wie, jak ustawić TTL dla wpisu pamięci podręcznej (w moim przypadku używam 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); }
w konfiguracji pamięci podręcznej musisz dodać te dwie metody fasoli, tworząc niestandardową instancję przechwytującą.
@Bean public CacheOperationSource cacheOperationSource() { return new AnnotationCacheOperationSource(); } @Primary @Bean public CacheInterceptor cacheInterceptor() { CacheInterceptor interceptor = new MyCustomCacheInterceptor(); interceptor.setCacheOperationSources(cacheOperationSource()); return interceptor; }
To rozwiązanie jest dobre, gdy chcesz ustawić TTL na poziomie podstawowym, a nie globalnie na poziomie pamięci podręcznej
źródło
Od wersji Spring-boot 1.3.3 można ustawić czas wygaśnięcia w CacheManager za pomocą RedisCacheManager.setExpires lub RedisCacheManager.setDefaultExpiration w komponencie bean wywołania zwrotnego CacheManagerCustomizer .
źródło
Podczas korzystania z Redis TTL można ustawić w pliku właściwości w następujący sposób:
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
źródło
Jeśli pracujesz z redis i Java 8, możesz rzucić okiem na JetCache :
@Cached(expire = 10, timeUnit = TimeUnit.MINUTES) User getUserById(long userId);
źródło