2011-11-18 15 views
53

Próbuję obsługiwać adnotację @Cacheable dla Spring 3.1 i zastanawiam się, czy istnieje jakiś sposób, aby wyczyścić buforowane dane po pewnym czasie, ustawiając TTL? W tej chwili, z tego co widzę, muszę sam to wyczyścić, używając @CacheEvict, i używając tego razem z @Scheduled mogę sam wykonać implementację TTL, ale wydaje mi się, że to trochę za tak proste zadanie?Czy mogę ustawić wartość TTL dla @Cacheable?

Odpowiedz

24

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

Jak mogę ustawić TTL polityki/TTI/Eksmisja/XXX funkcji?

Bezpośrednio za pośrednictwem dostawcy pamięci podręcznej. Pamięć podręczna jest abstrakcją ... dobrze, abstrakcją a nie realizacja cache

Tak więc, jeśli używasz ehcache użyć konfiguracji ehcache do skonfigurowania TTL.

Można również użyć Guva CacheBuilder do zbudowania pamięci podręcznej i przekazać widok ConcurrentMap tego cache do setStore method of the ConcurrentMapCacheFactoryBean.

27

Wiosna 3,1 guawa 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(); 
    } 

} 
+5

na wiosnę 4.1 przedłużyć CachingConfigurerSupport i tylko nadpisać cacheManager(). –

23

Oto przykład pełnego utworzenia Guava podręcznej na wiosnę. Użyłem Guavy zamiast Ehcache'a, ponieważ jest trochę lżejszy, a konfiguracja wydawała mi się prostsza.

importu Maven Zależności

Dodaj te zależności do pliku pom maven i uruchomić czyste i paczek. Pliki te to Guava dep i Spring Helper, które można wykorzystać 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> 

Konfiguracja Cache

Musisz utworzyć plik CacheConfig skonfigurować pamięć podręczną za pomocą config 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()); 
    } 
} 

Annotate metoda być buforowane

Dodaj @Cacheable adnotację i przekazać w imię 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żna zobaczyć pełniejszy przykład tutaj z Opatrzone komentarzem screeny: Guava Cache in Spring

15

używam lifehack tak

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

Wywołujesz metodę "reportCacheEvict" z dowolnego miejsca. Jak dzieje się cacheEvict? – Jaikrat

+0

Zdobądź. Nie wywołujemy tej metody z dowolnego miejsca. Jest wywoływany po ustalonym interwale czasowymDelay. Dzięki za podpowiedź. – Jaikrat

+0

Czyszczenie całej pamięci podręcznej z harmonogramu może być przydatnym narzędziem do poprawnego działania, ale ta metoda nie może być używana do nadawania pozycji TTL. Nawet wartość * condition * może zadeklarować, czy usunąć całą pamięć podręczną. U podstaw tego leży fakt, że ConcurrentMapCache przechowuje obiekty bez żadnego znacznika czasu, więc nie ma możliwości oceny TTL-as-is. – jmb

1

od wiosny-boot 1.3.3, można ustawić czas wygaśnięcia w menedżerze CacheManager za pomocą RedisCacheManager.setExpires lub RedisCacheManager.setDefaultExpiration w CacheManagerCustomizer bean-back.

13

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

} 

and

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

Amazing! Właśnie tego szukałem – MerLito

2

Można to zrobić poprzez rozszerzenie org.springframework.cache.interceptor.CacheInterceptor i nadpisać "doPut" metoda - org.springframework.cache.interceptor.AbstractCacheInvoker swoje logiczne ominięcie należy użyć metody put dostawcy cache, który wie ustawić TTL na wejściu bufora (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); 



} 

na CAC konfigurację tę należy dodać, aby dodać te metody 2-komponentowe, tworząc niestandardową instancję przechwytywania.

@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, jeśli chcesz ustawić TTL na poziomie podstawowym, a nie globalnie na poziomie cache

Powiązane problemy