@Cacheable에 대한 TTL을 설정할 수 있습니까?


101

@CacheableSpring 3.1에 대한 주석 지원을 시도하고 있으며 TTL을 설정하여 잠시 후 캐시 된 데이터를 지우는 방법이 있는지 궁금합니다. 지금 당장은를 사용하여 직접 정리해야하며 @CacheEvict함께 사용하여 @ScheduledTTL 구현을 직접 만들 수 있지만 그렇게 간단한 작업에는 약간 많은 것 같습니다.

답변:


39

http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#cache-specific-config 참조 하십시오 :

TTL / TTI / 퇴거 정책 / XXX 기능은 어떻게 설정하나요?

캐시 공급자를 통해 직접. 캐시 추상화는 ... 음, 추상화는 캐시 구현이 아닙니다.

따라서 EHCache를 사용하는 경우 EHCache의 구성을 사용하여 TTL을 구성하십시오.

Guava의 CacheBuilder 를 사용하여 캐시를 빌드하고이 캐시의 ConcurrentMap 뷰를 ConcurrentMapCacheFactoryBean의 setStore 메소드에 전달할 수도 있습니다.


57

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

}

21
Spring 4.1의 경우 CachingConfigurerSupport를 확장하고 cacheManager () 만 덮어 씁니다.
Johannes Flügel

39

다음은 Spring에서 Guava Cache를 설정하는 전체 예제입니다. 나는 Ehcache보다 Guava를 사용했는데 무게가 약간 가볍고 구성이 나에게 더 간단 해 보였습니다.

Maven 종속성 가져 오기

이러한 종속성을 maven pom 파일에 추가하고 clean 및 packages를 실행하십시오. 이 파일은 CacheBuilder에서 사용하기위한 Guava dep 및 Spring 도우미 메서드입니다.

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

캐시 구성

Java 구성을 사용하여 캐시를 구성하려면 CacheConfig 파일을 만들어야합니다.

@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 in Spring


2
참고 : Guava 캐시는 이제 Spring 5에서 더 이상 사용되지 않습니다 ( stackoverflow.com/questions/44175085/… )
Amin Ziaei 2018 년

33

이렇게 라이프 해킹을 사용합니다

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

reportCacheEvict어디서나 메서드 를 호출하고 있습니까? cacheEvict는 어떻게 발생합니까 ??
Jaikrat

그것을 얻으십시오. 우리는 어디에서나이 메서드를 호출하지 않습니다. fixedDelay 시간 간격 후에 호출됩니다. 힌트 주셔서 감사합니다.
Jaikrat

1
일정에 따라 전체 캐시를 지우는 것은 작업을 수행하는 데 편리한 해킹이 될 수 있지만이 방법은 항목에 TTL을 부여하는 데 사용할 수 없습니다. 조건 값 조차도 전체 캐시 삭제 여부 만 선언 할 수 있습니다. 기본적으로 ConcurrentMapCache는 타임 스탬프없이 객체를 저장하므로 TTL을있는 그대로 평가할 방법이 없습니다.
jmb

바지의 코드 시트입니다 (이 방법은 다음과 같습니다 :)).
Atum

멋지고 깨끗한 접근 방식
lauksas 19

30

스프링 부트 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(){
...
}

놀랄 만한! 이것이 내가 찾던 바로 그 것이었다
MerLito

6

이것은 org.springframework.cache.interceptor.CacheInterceptor를 확장하여 수행 할 수 있으며 "doPut"메소드를 재정의합니다-org.springframework.cache.interceptor.AbstractCacheInvoker 재정의 논리는 캐시 항목에 대해 TTL을 설정하는 것을 알고있는 캐시 공급자 put 메소드를 사용해야합니다. (제 경우에는 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);



}

캐시 구성에서 두 가지 bean 메소드를 추가하여 사용자 정의 인터셉터 인스턴스를 생성해야합니다.

@Bean
public CacheOperationSource cacheOperationSource() {
    return new AnnotationCacheOperationSource();
}


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

이 솔루션은 캐시 수준이 아닌 엔트리 수준에서 TTL을 설정하려는 경우에 적합합니다.


2

Spring-boot 1.3.3 이후부터는 CacheManagerCustomizer 콜백 빈 에서 RedisCacheManager.setExpires 또는 RedisCacheManager.setDefaultExpiration 을 사용하여 CacheManager에서 만료 시간을 설정할 수 있습니다 .


0

Redis를 사용할 때 TTL은 다음과 같이 속성 파일에서 설정할 수 있습니다.

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


-2

redis 및 Java 8을 사용하는 경우 JetCache를 살펴볼 수 있습니다 .

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


1
질문은 봄 @Cacheable 주석입니다
satyesht 19
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.