providers implementations example cacheable cache java spring

java - implementations - spring cache redis



¿Puedo configurar un TTL para @Cacheable (8)

Estoy probando el @Cacheable anotación @Cacheable para Spring 3.1 y me pregunto si hay alguna forma de borrar los datos en caché después de un tiempo configurando un TTL. Ahora mismo de lo que puedo ver, necesito aclararlo usando el @CacheEvict , y al usar eso junto con @Scheduled puedo hacer una implementación de TTL, pero parece demasiado para una tarea tan simple.


Aquí hay un ejemplo completo de cómo configurar Guava Cache en Spring. Usé Guava sobre Ehcache porque es un poco más liviano y la configuración me pareció más directa.

Importación Dependencias Maven

Agregue estas dependencias a su archivo maven pom y ejecute clean y packages. Estos archivos son los métodos Guava dep y Spring helper para usar en 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>

Configurar el caché

Necesita crear un archivo CacheConfig para configurar la memoria caché utilizando la configuración de 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()); } }

Anotar el método que se almacenará en caché

Agregue la anotación @Cacheable y pase el nombre de la memoria caché.

@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(); } }

Puede ver un ejemplo más completo aquí con capturas de pantalla anotadas: caché de guayaba en primavera


Desde Spring-boot 1.3.3, puede establecer el tiempo de caducidad en CacheManager utilizando RedisCacheManager.setExpires o RedisCacheManager.setDefaultExpiration en CacheManagerCustomizer call-back bean.


Primavera 3.1 y 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(); } }


Si está trabajando con redis y Java 8, puede echarle un vistazo a JetCache :

@Cached(expire = 10, timeUnit = TimeUnit.MINUTES) User getUserById(long userId);


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; } }

y

@Cacheable(value="A", cacheManager="timeoutCacheManager") public Object getA(){ ... }


Uso pirateo de la vida como este

@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())); }


Ver http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#cache-specific-config :

¿Cómo puedo configurar la función TTL / TTI / política de desalojo / XXX?

Directamente a través de su proveedor de caché. La abstracción de caché es ... bueno, una implementación de abstracción y no de caché

Entonces, si usa EHCache, use la configuración de EHCache para configurar el TTL.

También puede usar CacheBuilder de Guava para crear un caché y pasar la vista ConcurrentMap de este caché al método setStore del ConcurrentMapCacheFactoryBean .


esto se puede hacer extendiendo org.springframework.cache.interceptor.CacheInterceptor, y anulando el método "doPut" - org.springframework.cache.interceptor.AbstractCacheInvoker su lógica de anulación debe usar el método de almacenamiento del proveedor de caché que sabe establecer TTL para la entrada de caché (en mi caso uso 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); }

en su configuración de caché necesita agregar esos 2 métodos de bean, creando su instancia de interceptor personalizada.

@Bean public CacheOperationSource cacheOperationSource() { return new AnnotationCacheOperationSource(); } @Primary @Bean public CacheInterceptor cacheInterceptor() { CacheInterceptor interceptor = new MyCustomCacheInterceptor(); interceptor.setCacheOperationSources(cacheOperationSource()); return interceptor; }

Esta solución es buena cuando quiere establecer el TTL en el nivel de entrada, y no globalmente en el nivel de caché