Spring RedisCacheManager 用java代码获取缓存

 <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"> <constructor-arg name="redisOperations" ref="redisTemplate" /> </bean>

我配置了Redis作为缓存,集成在Spring中,目前的做法是直接在需要缓存的方法名上加@Cacheable(value = "xxx")实现缓存。

但我还有另外一个需求,就是在redis中存放登陆的用户。那这样在方法名上增加注解实现不了。需要直接用java代码添加及获取缓存。

我看了下RedisCacheManager的数据结构,但还是分析不出来怎么做。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/770430
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:spring boot2.0之自定义 RedisCacheManager 的方法
  • 除此之外, 这篇博客: 基于SpringBoot Redis Cache,封装一个能够批量操作(查询&保存)的缓存中的 封装 RedisMultiCache.java 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
    
    /**
     * 对 spring cache (redis实现) 进行了一层封装,主要包括以下两个
     * <ul>
     *     <li>对默认的Cache方法进行的一层封装,主要进行了try-cache处理,因为不希望因为读取缓存失败导致整个流程报错</li>
     *     <li>添加了批量查询和存入缓存的操作</li>
     * </ul>
     */
    public class RedisMultiCache implements Cache {
    
        private static final Logger log = LoggerFactory.getLogger(RedisMultiCache.class);
    
        /**
         * spring redis cache,
         */
        private Cache cache;
    
        private RedisTemplate redisTemplate;
    
        /**
         * 默认不清除原有缓存
         */
        public RedisMultiCache(Cache cache, RedisTemplate redisTemplate) {
            this(cache, redisTemplate, false);
        }
    
        /**
         * @param cache spring cache
         * @param redisTemplate 用于进行缓存的批量操作
         * @param clearExist 是否初始化缓存(清除redis中已经存在的缓存数据)
         */
        public RedisMultiCache(Cache cache, RedisTemplate redisTemplate, boolean clearExist) {
            this.cache = cache;
            this.redisTemplate = redisTemplate;
            // 创建缓存前, 是否初始化缓存,清除原有的
            if (clearExist) {
                cache.clear();
            }
        }
    
        @Override
        public String getName() {
            return cache.getName();
        }
    
        @Override
        public Object getNativeCache() {
            return cache.getNativeCache();
        }
    
        @Override
        public ValueWrapper get(Object key) {
            try {
                return cache.get(key);
            } catch (Exception e) {
                log.error("RedisMultiCache 异常", e);
            }
            return null;
        }
    
        @Override
        public <T> T get(Object key, Class<T> aClass) {
            try {
                return cache.get(key, aClass);
            } catch (Exception e) {
                log.error("RedisMultiCache 异常", e);
            }
            return null;
        }
    
        /**
         * 获取不为空的缓存,如果缓存中存在为null,则使用 valueLoader 重新加载,并将结果存入缓存中
         * @param key 缓存数据的key
         * @param valueLoader 加载缓存的方法
         * @return {@code null} if valueLoader returned null
         * @param <T> 缓存数据类型
         */
        public <T> T getNonNull(Object key, Callable<T> valueLoader) {
            T value;
            try {
                ValueWrapper wrapper = cache.get(key);
                if (wrapper == null || (value = (T) wrapper.get()) == null) {
                    value = valueLoader.call();
                    cache.put(key, value);
                }
            } catch (Exception e) {
                log.error("RedisMultiCache 异常", e);
                try {
                    return valueLoader.call();
                } catch (Exception ex) {
                    throw new RuntimeException(ex);
                }
            }
            return value;
        }
    
        /**
         * 如果缓存中存储的为null,则直接返回null
         * 如果 valueLoader 执行时抛出异常,则使用 RuntimeException 继续抛出,调用方自己处理
         * @return  {@code null} if cached null
         */
        @Override
        public <T> T get(Object key, Callable<T> valueLoader) {
            T value;
            try {
                value = cache.get(key, valueLoader);
            } catch (Exception e) {
                log.error("RedisMultiCache 异常", e);
                try {
                    return valueLoader.call();
                } catch (Exception ex) {
                    throw new RuntimeException(ex);
                }
            }
            return value;
        }
    
        @Override
        public void put(Object key, Object value) {
            try {
                cache.put(key, value);
            } catch (Exception e) {
                log.error("RedisMultiCache 异常", e);
            }
        }
    
        @Override
        public ValueWrapper putIfAbsent(Object key, Object value) {
            try {
                return cache.putIfAbsent(key, value);
            } catch (Exception e) {
                log.error("RedisMultiCache 异常", e);
            }
            return null;
        }
    
        @Override
        public void evict(Object key) {
            try {
                cache.evict(key);
            } catch (Exception e) {
                log.error("RedisMultiCache 异常", e);
            }
        }
    
        @Override
        public void clear() {
            try {
                cache.clear();
            } catch (Exception e) {
                log.error("RedisMultiCache 异常", e);
            }
        }
    
        /**
         * 批量读取缓存,默认 key-value 为一对一的关系
         * @see #list(List, Function, Function, Class, boolean)
         */
        public <K, V> List<V> list(List<K> keys, Function<Collection<K>, Collection<V>> valueLoader, Function<V, K> keyMapper, Class<V> vClass) {
            return list(keys, valueLoader, keyMapper, vClass, false);
        }
    
        /**
         * 批量获取缓存数据, 如不存在则通过 valueLoader 获取数据, 并存入缓存中
         * 如果缓存中存在 null,则视为不存在,仍然通过 valueLoader 加载,如需要防止缓存穿透,建议存入空对象,而非 null
         * @param keys        key
         * @param valueLoader 数据加载器
         * @param keyMapper   根据value获取key 映射器
         * @param vClass      返回数据类型
         * @param isListValue value是否为list类型,即一个key对应一个List<V>
         * @param <K>         key 的类型
         * @param <V>         value 的类型
         */
        @SuppressWarnings({"unchecked", "rawtypes"})
        public <K, V> List<V> list(List<K> keys, Function<Collection<K>, Collection<V>> valueLoader, Function<V, K> keyMapper, Class<V> vClass, boolean isListValue) {
            Objects.requireNonNull(redisTemplate, "redisTemplate required not null");
            List list0 = Collections.emptyList();
            try {
                list0 = redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
                    RedisSerializer keySerializer = redisTemplate.getKeySerializer();
                    for (K k : keys) {
                        byte[] key = keySerializer.serialize(createCacheKey(k));
                        if (key != null) {
                            connection.get(key);
                        } else {
                            log.warn("RedisMultiCache 批量操作序列化失败, key={}", k);
                        }
                    }
                    return null;
                });
            } catch (Exception e) {
                log.error("RedisMultiCache 异常", e);
            }
    
            int size = keys.size();
            // 缓存不存在的key
            List<K> nkeys = new ArrayList<>(size);
            List<V> values = new ArrayList<>(size);
            if (CollectionUtils.isEmpty(list0)) {
                nkeys.addAll(keys);
            } else {
                for (int i = 0; i < list0.size(); i++) {
                    Object o = list0.get(i);
                    if (o == null) {
                        nkeys.add(keys.get(i));
                    } else {
                        // redis中存储的是 JsonObject 或 JsonArray 对象
                        if (o instanceof JSONArray) {
                            values.addAll(((JSONArray) o).toJavaList(vClass));
                        } else if (o instanceof JSONObject) {
                            values.add(JSONObject.toJavaObject((JSONObject) o, vClass));
                        }
                    }
                }
            }
    
            if (!CollectionUtils.isEmpty(nkeys)) {
                Collection<V> nValue = valueLoader.apply(nkeys);
                Map kvMap;
                if (isListValue) {
                    kvMap = nValue.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(keyMapper));
                } else {
                    kvMap = nValue.stream().filter(Objects::nonNull).collect(Collectors.toMap(keyMapper, Function.identity()));
                }
                putBatch(kvMap);
                values.addAll(nValue);
            }
            return values;
        }
    
        /**
         * 批量存入缓存
         * @param map 需要存入的数据
         * @param <K> 数据的 key 的类型
         * @param <V> 数据的 value 的类型
         */
        @SuppressWarnings({"unchecked", "rawtypes"})
        public <K, V> void putBatch(Map<K, V> map) {
            if (CollectionUtils.isEmpty(map)) {
                return;
            }
    
            Objects.requireNonNull(redisTemplate, "redisTemplate required not null");
            try {
                redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
                    RedisSerializer keySerializer = redisTemplate.getKeySerializer();
                    RedisSerializer valueSerializer = redisTemplate.getValueSerializer();
                    for (Map.Entry<K, V> entry : map.entrySet()) {
                        byte[] key = keySerializer.serialize(createCacheKey(entry.getKey()));
                        byte[] value = valueSerializer.serialize(entry.getValue());
                        if (key != null && value != null) {
                            connection.set(key, value);
                        } else {
                            log.warn("RedisMultiCache 批量操作序列化失败, entry={}", entry);
                        }
                    }
                    return null;
                });
            } catch (Exception e) {
                log.error("RedisMultiCache 异常", e);
            }
        }
    
        /**
         * @param key 缓存数据的key
         * @param <K> key 的类型
         * @return 缓存数据在 redis 中的 key
         */
        private <K> String createCacheKey(K key) {
            return RedisCacheConfig.computeCachePrefix(getName())+ key.toString();
        }
    }
    

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^