Tôi có thể đặt TTL cho @Cacheable không


100

Tôi đang thử @Cacheablehỗ trợ chú thích cho Spring 3.1 và tự hỏi liệu có cách nào để xóa dữ liệu đã lưu trong bộ nhớ cache sau một thời gian bằng cách đặt TTL không? Ngay bây giờ từ những gì tôi có thể thấy, tôi cần phải tự giải quyết nó bằng cách sử dụng @CacheEvictvà bằng cách sử dụng nó cùng với @Scheduledtôi có thể tự thực hiện TTL nhưng có vẻ hơi nhiều cho một nhiệm vụ đơn giản như vậy?

Câu trả lời:


39

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

Làm cách nào để đặt tính năng TTL / TTI / Trục xuất / XXX?

Trực tiếp thông qua nhà cung cấp bộ nhớ cache của bạn. Sự trừu tượng hóa bộ nhớ cache là ... tốt, một sự trừu tượng hóa không phải là một triển khai bộ nhớ cache

Vì vậy, nếu bạn sử dụng EHCache, hãy sử dụng cấu hình của EHCache để cấu hình TTL.

Bạn cũng có thể sử dụng CacheBuilder của Guava để tạo bộ nhớ cache và chuyển chế độ xem Bản đồ đồng thời của bộ nhớ cache này sang phương thức setStore của ConcurrentMapCacheFactoryBean .


57

Spring 3.1 và 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
Đối với Spring 4.1, hãy mở rộng CachingConfigurerSupport và chỉ ghi đè cacheManager ().
Johannes Flügel,

39

Đây là một ví dụ đầy đủ về cách thiết lập Guava Cache trong Spring. Tôi đã sử dụng Guava thay vì Ehcache vì nó có trọng lượng nhẹ hơn một chút và cấu hình có vẻ dễ hiểu hơn đối với tôi.

Nhập phụ thuộc Maven

Thêm các phần phụ thuộc này vào tệp maven pom của bạn và chạy sạch và các gói. Các tệp này là các phương thức trợ giúp Guava dep và Spring để sử dụng trong 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>

Định cấu hình bộ nhớ cache

Bạn cần tạo tệp CacheConfig để cấu hình bộ đệm bằng cấu hình 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());
   }
}

Chú thích phương thức được lưu vào bộ nhớ đệm

Thêm chú thích @Cacheable và nhập tên bộ nhớ cache.

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

Bạn có thể xem một ví dụ đầy đủ hơn ở đây với ảnh chụp màn hình có chú thích: Guava Cache in Spring


2
Lưu ý: Ổi bộ nhớ cache hiện đang bị phản đối trong mùa xuân 5 ( stackoverflow.com/questions/44175085/... )
Amin Ziaei

33

Tôi sử dụng cuộc sống hack như thế này

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

Bạn có đang gọi reportCacheEvictphương thức từ bất cứ đâu. CacheEvict diễn ra như thế nào ??
Jaikrat

Hiểu rồi. Chúng tôi không gọi phương pháp này từ bất kỳ đâu. Nó được gọi sau khoảng thời gian fixedDelay. Cảm ơn cho gợi ý.
Jaikrat

1
Xóa toàn bộ bộ nhớ cache theo lịch trình có thể là một thủ thuật hữu ích để làm cho mọi thứ hoạt động, nhưng phương pháp này không thể được sử dụng để cung cấp cho các mục một TTL. Ngay cả giá trị điều kiện cũng chỉ có thể khai báo có xóa toàn bộ bộ nhớ đệm hay không. Cơ bản của điều này là ConcurrentMapCache lưu trữ các đối tượng mà không có bất kỳ dấu thời gian nào, vì vậy không có cách nào để đánh giá TTL như hiện tại.
jmb

là mã chỗ ngồi của quần (phương pháp này đã được viết nguệch ngoạc :)).
Atum

Đẹp và cách tiếp cận sạch
lauksas

30

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

Kinh ngạc! Đây chính xác là những gì tôi đang tìm kiếm
MerLito

6

điều này có thể được thực hiện bằng cách mở rộng org.springframework.cache.interceptor.CacheInterceptor và ghi đè phương thức "doPut" - org.springframework.cache.interceptor.AbstractCacheInvoker logic ghi đè của bạn nên sử dụng phương thức đặt của nhà cung cấp bộ nhớ cache biết đặt TTL cho mục nhập bộ nhớ cache (trong trường hợp của tôi, tôi sử dụng 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);



}

trên cấu hình bộ nhớ cache của bạn, bạn cần thêm 2 phương thức bean đó, tạo phiên bản chặn tùy chỉnh của bạn.

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


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

Giải pháp này tốt khi bạn muốn đặt TTL ở cấp mục nhập chứ không phải trên toàn cục ở cấp bộ nhớ cache


2

Kể từ Spring-boot 1.3.3, bạn có thể đặt thời gian hết hạn trong CacheManager bằng cách sử dụng RedisCacheManager.setExpires hoặc RedisCacheManager.setDefaultExpiration trong đậu gọi lại CacheManagerCustomizer .


0

Khi sử dụng Redis, TTL có thể được đặt trong tệp thuộc tính như sau:

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

Nếu bạn đang làm việc với redis và Java 8, bạn có thể xem qua JetCache :

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


1
câu hỏi là cho mùa xuân @Cacheable chú thích
satyesht
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.