咖啡因缓存刷新/手动或按需重新加载缓存

7
我已在我的应用程序中实现了咖啡因缓存。我正在从一些静态表中缓存数据。但是我想知道是否可以使用REST API或其他方式手动刷新/清除/重新加载缓存,或按需执行此操作。请问有什么方法可以实现这样的要求。
我希望有一个类似于以下的东西: 一个端点URL,如:http://localhost:8080/refreshCache 这将在内部触发某些方法,并手动清除缓存或重新加载新值。
以下是缓存配置:
@Configuration
public class CacheConfig{

     private com.github.benmanes.caffeine.cache.Cache<Object, Object> cache;

    @Bean
    Caffeine<Object,Object> cacheBuilder(){
        return Caffeine.newBuilder()
                .initialCapacity(300)
                .maximumSize(50000)
                .expireAfterAccess(1, TimeUnit.DAYS)
                .removalListener(new CacheRemovalListener())
                .recordStats();
    }

    class CacheRemovalListener implements RemovalListener<Object, Object> {
        @Override
        public void onRemoval(Object key, Object value, RemovalCause cause) {
            System.out.format("Removal listener called with key [%s], cause[%s], evicted [%s] %n", 
                    key , cause.toString(), cause.wasEvicted());
        }
    }

} 

1
如果您有缓存实例,则可以调用 invalidateAll() 方法来清除它。如果您正在使用 Spring Cache,请查阅其文档以了解清除功能。 - Ben Manes
我还想检查缓存中有哪些值/元素,或者已经缓存了哪些元素。我该如何检查缓存的值? - Animesh
@Ben:你能提供一些代码吗?我尝试过了,但是在我尝试相同的时候它抛出了异常。 - Animesh
System.out.println(cache.asMap()) 应该足够作为初步调试的依据。 - Ben Manes
我可以使用这个cache.asMap(),但是假设我已经在某个cacheConfig.java文件中配置了缓存,并且我想在某个cacheUtility.java文件中获取缓存中存储的值,那么我该如何在实用程序文件中获取此缓存。 另外,考虑到我为我的应用程序配置了n个基于特定名称的缓存,即每个缓存都有单独的名称。在这种情况下,假设我想要缓存名为xyzCache的缓存数据,那么我该如何仅获取该xyzCache的缓存数据? - Animesh
显示剩余6条评论
1个回答

8
您可以使用Spring的CacheManager创建CaffeineCache实例,然后可以使用CacheManager对任何缓存执行CRUD操作。
请参阅下面的代码。
Bean配置:
public class CacheBeansConfig {

  @Bean
  public CacheManager cacheManager() {
    // create multiple instances of cache
    CaffeineCacheManager cacheManager = new CaffeineCacheManager("UserCache","InventoryCache");
    cacheManager.setCaffeine(caffeineCacheBuilder());
    return cacheManager;
  }

  private Caffeine<Object, Object> caffeineCacheBuilder() {

    return Caffeine.newBuilder()
        .initialCapacity(<initial capacity>)
        .maximumSize(<max size>)
        .expireAfterAccess(<expire after hrs>, TimeUnit.HOURS)
        .recordStats();
  }

这将使用两个Caffeine Cache实例初始化您的CacheManager。
使用以下Rest Controller类来访问这些类。
@RestController
@RequestMapping(path = "/v1/admin/cache")
public class ACSCacheAdminController {

  @Autowired
  private CacheManager cacheManager;

  /**
   * call this to invalidate all cache instances
   */
  @DeleteMapping(
      path = "/",
      produces = {"application/json"})
  public void invalidateAll() {
    Collection<String> cacheNames = cacheManager.getCacheNames();
    cacheNames.forEach(this::getCacheAndClear);
  }

  /**
   * call this to invalidate a given cache name
   */
  @DeleteMapping(
      path = "/{cacheName}",
      produces = {"application/json"})
  public void invalidateCache(@PathVariable("cacheName") final String cacheName) {
    getCacheAndClear(cacheName);
  }

  /**
   * Use this to refresh a cache instance
   */
  @PostMapping(
      path = "/{cacheName}",
      produces = {"application/json"})
  public void invalidateCache(@PathVariable("cacheName") final String cacheName) {
    getCacheAndClear(cacheName);
    Cache cache = cacheManager.getCache(cacheName);
    // your logic to put in above cache instance
    // use cache.put(key,value)
  }


  /**
   * call this to invalidate cache entry by given cache name and cache key
   */
  @DeleteMapping(
      path = "/{cacheName}/{key}/",
      produces = {"application/json"})
  public void invalidateCacheKey(
      @PathVariable("cacheName") final String cacheName, @PathVariable("key") Object key) {
    final Cache cache = cacheManager.getCache(cacheName);
    if (cache == null) {
      throw new IllegalArgumentException("invalid cache name for key invalidation: " + cacheName);
    }
    cache.evict(key);
  }

  @GetMapping(
      path = "/{cacheName}/{key}",
      produces = {"application/json"})
  public ResponseEntity<Object> getByCacheNameAndKey(
      @PathVariable("cacheName") final String cacheName, @PathVariable("key") final int key) {
    final Cache cache = cacheManager.getCache(cacheName);
    if (cache == null) {
      throw new IllegalArgumentException("invalid cache name: " + cacheName);
    }
    return ResponseEntity.ok().body(cache.get(key));
  }

  private void getCacheAndClear(final String cacheName) {

    final Cache cache = cacheManager.getCache(cacheName);
    if (cache == null) {
      throw new IllegalArgumentException("invalid cache name: " + cacheName);
    }
    cache.clear();
  }

根据您的需要更改代码即可 :)


这正是我想要做的,但我无法让配置工作,因为在我的Spring版本(4.3.10)中找不到org.springframework.cache.caffeine.CaffeineCacheManager。那是仅适用于Spring Boot的软件包,还是我缺少依赖项?我确实在我的deps中有Caffeine,其软件包也可用。谢谢。 - Madbreaks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接