fuweiza9166 2017-03-27 02:10 采纳率: 0%
浏览 2019

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的数据结构,但还是分析不出来怎么做。

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2022-09-21 01:55
    关注
    不知道你这个问题是否已经解决, 如果还没有解决的话:
    • 这有个类似的问题, 你可以参考下: 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();
          }
      }
      

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

报告相同问题?

悬赏问题

  • ¥100 有人会搭建GPT-J-6B框架吗?有偿
  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名