• springboot 调用redisTemplate时总是为null的解决方法


    在SpringBoot项目中,Spring会自动配置好RedisTemplate,看下源码。

    从源码可以看出,SpringBoot自动帮我们在容器中生成了一个RedisTemplate和一个StringRedisTemplate。但是,这个RedisTemplate的泛型是<Object,Object>,写代码不方便,需要写好多类型转换的代码;我们需要一个泛型为<String,Object>形式的RedisTemplate。

            看到这个@ConditionalOnMissingBean注解后,就知道如果Spring容器中已经有了RedisTemplate对象了,这个自动配置的RedisTemplate就不会再实例化。因此我们可以自己写个配置类,配置RedisTemplate进行实例化。

    既然自动配置不好用,就重新配置一个RedisTemplate,在工具类的同一目录下创建RedisConfig 配置类。

    代码如下:第一步:

    @Configuration
    @EnableCaching
    public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    @SuppressWarnings(value = {"unchecked", "rawtypes"})
    public RedisTemplate<Object, Object> redisTemplate(RedissonConnectionFactory connectionFactory) {
    RedisTemplate<Object, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory);

    FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
    ObjectMapper mapper = new ObjectMapper();
    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
    serializer.setObjectMapper(mapper);

    template.setValueSerializer(new StringRedisSerializer());
    // 使用StringRedisSerializer来序列化和反序列化rediskey
    template.setKeySerializer(new StringRedisSerializer());
    template.afterPropertiesSet();
    return template;
    }
    }
    =======================================================================================================================
    配置好之后,可以再增加一个通用工具类,代码如下:
    第二步:
    package com.ykh.fwt.common.config.redis;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.BoundSetOperations;
    import org.springframework.data.redis.core.HashOperations;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.ValueOperations;
    import org.springframework.stereotype.Component;

    import java.util.*;
    import java.util.concurrent.TimeUnit;

    /**
    * spring redis 工具类
    *
    * @author lzb
    */
    @SuppressWarnings(value = {"unchecked", "rawtypes"})
    @Component
    public class RedisCache {
    @Autowired
    public RedisTemplate redisTemplate;

    /**
    * 缓存基本的对象,IntegerString、实体类等
    *
    * @param value 缓存的值
    */
    public <T> void setCacheObject(final String key, final T value) {
    redisTemplate.opsForValue().set(key, value);
    }

    /**
    * 缓存基本的对象,IntegerString、实体类等
    *
    * @param timeUnit 时间颗粒度
    */
    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
    redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }

    /**
    * 获得缓存的基本对象。
    *
    * @param key 缓存键值
    * @return 缓存键值对应的数据
    */
    public <T> T getCacheObject(final String key) {
    ValueOperations<String, T> operation = redisTemplate.opsForValue();
    return operation.get(key);
    }

    /**
    * 设置有效时间
    *
    * @param timeout 超时时间
    * @return true=设置成功;false=设置失败
    */
    public boolean expire(final String key, final long timeout) {
    return expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
    * 设置有效时间
    *
    * @param timeout 超时时间
    * @return true=设置成功;false=设置失败
    */
    public boolean expire(final String key, final long timeout, final TimeUnit unit) {
    return redisTemplate.expire(key, timeout, unit);
    }

    /**
    * 获取过期时间,单位: , -1 无过期时间, -2 不存在此键
    *
    * @param key the key
    * @param unit 时间单位
    * @return the long
    */
    public Long getExpire(final String key, final TimeUnit unit) {
    return redisTemplate.getExpire(key, unit);
    }

    /**
    * 删除单个对象
    *
    * @param key
    */
    public boolean deleteObject(final String key) {
    return redisTemplate.delete(key);
    }

    /**
    * 删除集合对象
    *
    * @param collection 多个对象
    * @return
    */
    public long deleteObject(final Collection collection) {
    return redisTemplate.delete(collection);
    }

    /**
    * 缓存List数据
    *
    * @param dataList 待缓存的List数据
    * @return 缓存的对象
    */
    public <T> long setCacheList(final String key, final List<T> dataList) {
    Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
    return count == null ? 0 : count;
    }

    /**
    * 获得缓存的list对象
    *
    * @param key 缓存的键值
    * @return 缓存键值对应的数据
    */
    public <T> List<T> getCacheList(final String key) {
    return redisTemplate.opsForList().range(key, 0, -1);
    }

    /**
    * 缓存Set
    *
    * @param dataSet 缓存的数据
    * @return 缓存数据的对象
    */
    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) {
    BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
    Iterator<T> it = dataSet.iterator();
    {
    setOperation.add(it.next());
    }
    return setOperation;
    }

    /**
    * 获得缓存的set
    *
    * @param key
    * @return
    */
    public <T> Set<T> getCacheSet(final String key) {
    return redisTemplate.opsForSet().members(key);
    }

    /**
    * 缓存Map
    *
    * @param key
    * @param dataMap
    */
    public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
    if (dataMap != null) {
    redisTemplate.opsForHash().putAll(key, dataMap);
    } }


    /**
    * 获得缓存的Map
    *
    * @param key
    * @return
    */
    public <T> Map<String, T> getCacheMap(final String key) {
    return redisTemplate.opsForHash().entries(key);
    }

    /**
    * Hash中存入数据
    *
    * @param value
    */
    public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
    redisTemplate.opsForHash().put(key, hKey, value);
    }

    /**
    * 获取Hash中的数据
    *
    * @param hKey Hash
    * @return Hash中的对象
    */
    public <T> T getCacheMapValue(final String key, final String hKey) {
    HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
    return opsForHash.get(key, hKey);
    }

    /**
    * 获取多个Hash中的数据
    *
    * @param hKeys Hash键集合
    * @return Hash对象集合
    */
    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
    return redisTemplate.opsForHash().multiGet(key, hKeys);
    }

    /**
    * 获得缓存的基本对象列表
    *
    * @param pattern 字符串前缀
    * @return 对象列表
    */
    public Collection<String> keys(final String pattern) {
    return redisTemplate.keys(pattern);
    }


    /**
    * Exists key boolean.
    *
    * @param key the key
    * @return the boolean
    */
    public boolean existsKey(String key) {
    return redisTemplate.hasKey(key);
    }}
    ==================================================================================================================
    第三步:增加完第一步和第二步的类文件之后,在Controller里面进行调用
    @RestController
    @RequestMapping("/goods/goods")
    @Api(tags ="平台端-商品管理")
    public class GoodsController extends BaseController
    {

    @Autowired
    private RedisCache redisCache;

     //删除商品缓存
    String cacheKey = String.format("%s.%s", DataCacheKeys.FWT_GOODS, goods.getCode());
    boolean existsKey=redisCache.existsKey(cacheKey);
    if (existsKey){
    redisCache.deleteObject(cacheKey);
    }

    }

    切记:一定要用@Autowired进行注入,要不然redisTemplate会一直为null。



  • 相关阅读:
    如何将程序集(dll)安装到全局程序集缓存(GAC)中
    当 ftp 遇上 http Proxy
    sql server 2008 帶主鍵table 字段 數據類型修改
    SQL 按指定顺序进行排序
    当发布时报错: 找不到 obj\Debug\Package\PackageTmp\xxx.aspx 文件
    c# 简体 繁体 转换
    SQL SERVER 简体与繁体 定序 轉換
    匿名类型与Lambda表达式
    使用委托实现了在循环中调用不同的方法
    学习源代码的心得
  • 原文地址:https://www.cnblogs.com/zbliao/p/14298482.html
Copyright © 2020-2023  润新知