【问题标题】:How to Iterate on a cache entries如何迭代缓存条目
【发布时间】:2012-08-03 11:44:21
【问题描述】:

我在独立环境中使用 Spring3.1。 我正在使用 @Cachable 注释缓存我的条目。

有时我需要迭代缓存列表以获得特定值(不是键)。

所以我设法检索了缓存列表,但我如何迭代它的元素。

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

谢谢, 射线。

【问题讨论】:

    标签: java spring caching ehcache


    【解决方案1】:

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

    编辑: 根据 Spring it doesn't look like they will ever support 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;
    }
    

    【讨论】:

    • 但我没有 cache.getKeys() 方法。我正在使用 org.springframework.cache.Cache
    • 您找到解决方案了吗?如何迭代 infinispan 缓存。我需要钥匙。
    • 你投到底层提供者了吗?
    • 这个答案假定继承的 Cache 类型对象有一个 getKeys 方法。这并不总是正确的,如上所述,org.springframework.cache.Cache 不包括这种缓存。
    【解决方案2】:

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

    更多详情请阅读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);
        }
    

    【讨论】:

      【解决方案3】:

      下面的方法会给出一组缓存对象的键,但是在这里如果你用键添加缓存,那么很容易检索(如果你直接添加对象列表到缓存,那么它就行不通了)。

      另外,我在缓存管理器中使用了 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;
      }
      

      【讨论】:

        【解决方案4】:

        我用这个

        第一个端点会告诉你你拥有的缓存

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

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

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

        【讨论】:

          【解决方案5】:
          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()
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-10-29
            • 2014-11-22
            • 2022-01-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-03-14
            • 2015-08-14
            相关资源
            最近更新 更多