Подтвердить что ты не робот

Могу ли я установить TTL для @Cacheable

Я пробовал поддержку аннотации @Cacheable для Spring 3.1 и задаюсь вопросом, есть ли способ сделать кэшированные данные очищенными через некоторое время, установив TTL? Прямо сейчас из того, что я вижу, мне нужно очистить себя, используя @CacheEvict, и, используя это вместе с @Scheduled, я могу сделать реализацию TTL сам, но для такой простой задачи это немного похоже?

4b9b3361

Ответ 1

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

Как установить функцию TTL/TTI/Eviction policy/XXX?

Непосредственно через поставщика кешей. Абстракция кэша... ну, абстракция не реализация кэша

Итак, если вы используете EHCache, используйте конфигурацию EHCache для настройки TTL.

Вы также можете использовать Guava CacheBuilder для создания кеша и передать этот кеш. Просмотр ConcurrentMap в setStore метод ConcurrentMapCacheFactoryBean.

Ответ 2

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

}

Ответ 3

Вот полный пример настройки кэша Guava в Spring. Я использовал Гуаву над Ehcache, потому что это немного более легкий вес, и конфигурация казалась мне более прямой.

Импортировать зависимости Maven

Добавьте эти зависимости к вашему файлу maven mam и выполните очистку и пакеты. Эти файлы представляют собой вспомогательные методы 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 в Spring

Ответ 4

Я использую такой хакерский взлом

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

Ответ 5

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(){
...
}

Ответ 6

Поскольку Spring -boot 1.3.3, вы можете установить время истечения срока действия в CacheManager с помощью RedisCacheManager.setExpires или RedisCacheManager.setDefaultExpiration в CacheManagerCustomizer обратный вызов bean.

Ответ 7

это можно сделать, расширив org.springframework.cache.interceptor.CacheInterceptor и переопределив метод doPut - org.springframework.cache.interceptor.AbstractCacheInvoker ваша логика переопределения должна использовать метод put provider cache, который знает, чтобы установить 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 на начальном уровне, а не глобально на уровне кеша