如何迭代缓存条目

11
我在独立环境中使用Spring3.1。 我正在使用@Cacheable注释缓存我的条目。
有时,我需要迭代缓存列表以获取特定值(不是键)。 因此,我设法检索缓存列表,但如何迭代其元素?
private ClientDTO getClientDTOByClientId(Integer clientId)
{

    Cache clientCache = null;
    try
    {
        clientCache = ehCacheCacheManager.getCache("client");

          //need here to iterate on clientCache. how?


    }
    catch (Exception e)
    {
        log.error("Couldnt retrieve client from cache. clientId=" + clientId);
    }
    return clientDTO;
}

我正在使用ehcache机制。

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
        p:cache-manager-ref="ehcache" />

    <bean id="ehcache"
        class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
        p:config-location="classpath:ehcache.xml" />
感谢你,雷。
5个回答

17

CacheManager.getCache() 返回一个 net.sf.ehcache.Cache 对象,它有一个 getKeys() 方法,可以返回一个缓存键的列表,您可以对其进行迭代。要检索实际存储的对象(而不是包装的 net.sf.ehcache.Element),请使用 Element.getObjectValue()。

编辑: 根据 Spring 的说法看起来他们永远不会支持 Cache.getKeys(), 所以您需要将其转换为基础提供程序。

像这样:

public boolean contains(String cacheName, Object o) {
  net.sf.ehcache.EhCache cache = (net.sf.ehcache.EhCache) org.springframework.cache.CacheManager.getCache(cacheName).getNativeCache();
  for (Object key: cache.getKeys()) {
    Element element = cache.get(key);
    if (element != null && element.getObjectValue().equals(o)) {
      return true;
    }
  }
  return false;
}

8
但是我没有cache.getKeys()方法。我正在使用org.springframework.cache.Cache。 - rayman
1
你找到解决方案了吗?如何迭代Infinispan缓存。我需要键。 - G dangi
2
你是否转换为基础提供程序? - Matt Brock
此答案假设继承的Cache类型对象具有getKeys方法。这并不总是正确的,正如上面提到的一个缓存org.springframework.cache.Cache就不包括此方法。 - Michael Rountree
无法将“class org.springframework.cache.ehcache.EhCacheCache”转换为“class net.sf.ehcache.Ehcache” - ka3ak
请检查是否调用了.getNativeCache()以获取底层缓存管理器实现。 - Matt Brock

8

另一种解决方案是使用getNativeCache()方法将org.springframework.cache.Cache转换为javax.cache.Cache,并使用java迭代器,因为javax.cache.Cache已经扩展了Iterable<Cache.Entry<K, V>>。

更多细节请阅读javax.cache.Cache javadoc

    Cache cache = (Cache) cacheManager.getCache("yourCacheName").getNativeCache();
    Iterator<Cache.Entry> iterator = cache.iterator();

    while (iterator.hasNext()) {
        String key = (String) iterator.next().getKey();
        System.out.println(key);
    }

1
var cache = cacheManager.getCache("CACHE_NAME");
var nativeCache = (ConcurrentHashMap<?, ?>) cache.getNativeCache();

for (var entry: nativeCache.entrySet()){
    // Access entry key and value
    entry.getKey()
    entry.getValue()
}

0
下面的方法将返回一组缓存对象的键,但是如果您将缓存与键一起添加,则很容易检索(如果直接将对象列表添加到缓存中,则无法正常工作)。
此外,我在缓存管理器中使用了GuavaCache,如下所示。
@Bean
public CacheManager cacheManager() {
    SimpleCacheManager simpleCacheManager = new SimpleCacheManager();

    GuavaCache userLabCache = new GuavaCache("yourCacheName",
            CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build());
    simpleCacheManager.setCaches(Arrays.asList(userLabCache));
    return simpleCacheManager;
}

然后它将返回键列表作为对象,您可以获取这些键并遍历这些键,从缓存中逐个获取对象。

在您的类中自动装配Springboot CacheManager

@Autowired
CacheManager cacheManager;

以下是获取所有键的代码。
public Set<Object> getAllCachedUserLabKeys() {
    Set<Object> keys = null;
    try {
        GuavaCache cache = (GuavaCache) cacheManager.getCache("yourCacheName");
        if (cache != null) {
            ConcurrentMap<Object, Object> cachedMap = cache.getNativeCache().asMap();
            keys = cachedMap.keySet();
        }
    } catch (Exception e) {
        LOGGER.error("Unknown exception occured while fetchting all cached User Labs..!", e);
    }
    return keys;
}

0

我使用这个

第一个端点将告诉您您拥有的缓存

第二个端点将为您提供特定缓存的所有条目(带安全映射)

第三个端点将为您提供所有缓存的所有条目(带安全映射)

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.github.benmanes.caffeine.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;

@RestController
@RequestMapping("cache")
public class CacheController {
    private final CacheManager cacheManager;
    private final ObjectMapper objectMapper;

    public CacheController(final CacheManager cacheManager) {
        this.cacheManager = cacheManager;
        this.objectMapper = new ObjectMapper();
        this.objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        this.objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    }

    @GetMapping("/names")
    public Collection<String> getCacheNames() {
        return cacheManager.getCacheNames();
    }

    @GetMapping("{cacheName}")
    public Map<String, Object> getEntriesForCache(@PathVariable(name = "cacheName") final String cacheName) throws JsonProcessingException {
        final Cache<String, Object> cache = (Cache<String, Object>) cacheManager.getCache(cacheName).getNativeCache();

        final ConcurrentMap<String, Object> data = cache.asMap();
        final String json = objectMapper.writeValueAsString(data);

        final TypeReference<HashMap<String,Object>> typeRef = new TypeReference<>() {};
        return objectMapper.readValue(json, typeRef);
    }

    @GetMapping("entries")
    public Map<String, Map<String, Object>> getAllEntries() throws JsonProcessingException {
        final Map<String, Map<String, Object>> entries = new HashMap<>();
        for(final String cacheName: getCacheNames()){
            entries.put(cacheName, getEntriesForCache(cacheName));
        }
        return entries;
    }
}

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