zoukankan      html  css  js  c++  java
  • springBoot--Redis配置与使用

    SpringBoot自动配置redis,主要是两个自动配置类

    缓存管理器配置类:org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
    
    redis封装了工具RedisTemplate自动配置:org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

    缓存管理器CacheManager配置,@Cacheable,@CacheEvict、@CachePut 

    我们使用@Cacheable,@CacheEvict、@CachePut 这些缓存注解的时候需要配置CacheManager,也就是需要可以参考RedisCacheConfiguration配置

    springBoot的缓存管理器CacheManager封装了常用的缓存工具,

    内存缓存:基于java8的高性能内存缓存Caffeine;JCache,EhCache
    
    noSQL数据库缓存(Couchbase,Redis)
    
    其他:Infinispan 基于Apache 2.0协议的分布式键值存储系统

    如果没有默认配置自定义的CacheManager时,RedisCacheConfiguration配置会生效

    这个类配置的缓存管理器使用的是 JdkSerializationRedisSerializer 序列化,缓存数据在redis存储是以字节形式存储,不能再redis数据库查看

    我们如果要自定义序列化,需要自定义CacheManager 这个Bean

    package com.zwh.config.cache;
    
    import org.springframework.beans.factory.ObjectProvider;
    import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizers;
    import org.springframework.boot.autoconfigure.cache.CacheProperties;
    import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.cache.RedisCacheManager;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.RedisSerializationContext;
    
    import java.util.LinkedHashSet;
    import java.util.List;
    
    /**
     * redis缓存配置,搭配@Cache()注解使用, 要直接操作Redis缓存配置,请到{@link com.zwh.config.RedisConfig}
     * 重写org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
     * @author monkey
     * @date 2020/7/17
     * @since 1.8
     */
    @Configuration(proxyBeanMethods = false)
    @EnableConfigurationProperties({CacheProperties.class})
    @EnableCaching
    public class RedisCacheConfiguration {
    
        @Bean
        RedisCacheManager cacheManager(
                CacheProperties cacheProperties,
                ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration,
                ObjectProvider<RedisCacheManagerBuilderCustomizer> redisCacheManagerBuilderCustomizers,
                RedisConnectionFactory redisConnectionFactory
        ) {
            RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(
                    determineConfiguration(cacheProperties, redisCacheConfiguration));
            List<String> cacheNames = cacheProperties.getCacheNames();
            if (!cacheNames.isEmpty()) {
                builder.initialCacheNames(new LinkedHashSet<>(cacheNames));
            }
            redisCacheManagerBuilderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
            return new CacheManagerCustomizers(null).customize(builder.build());
        }
    
        private org.springframework.data.redis.cache.RedisCacheConfiguration determineConfiguration(
                CacheProperties cacheProperties,
                ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration
        ) {
            return redisCacheConfiguration.getIfAvailable(() -> createConfiguration(cacheProperties));
        }
    
        private org.springframework.data.redis.cache.RedisCacheConfiguration createConfiguration(
                CacheProperties cacheProperties) {
            CacheProperties.Redis redisProperties = cacheProperties.getRedis();
            org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration
                    .defaultCacheConfig();
            config = config.serializeValuesWith(
                    RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())
            );
            if (redisProperties.getTimeToLive() != null) {
                config = config.entryTtl(redisProperties.getTimeToLive());
            }
            if (redisProperties.getKeyPrefix() != null) {
                config = config.prefixKeysWith(redisProperties.getKeyPrefix());
            }
            if (!redisProperties.isCacheNullValues()) {
                config = config.disableCachingNullValues();
            }
            if (!redisProperties.isUseKeyPrefix()) {
                config = config.disableKeyPrefix();
            }
            return config;
        }
    
    }
    View Code

    这个配置后,就可以将缓存的对象数据以json的形式存储到redis数据库

    编写测试接口

        @RequestMapping("/testRedisManagerCache")
        @ResponseBody
        @Cacheable(value = "haha1")
        public List<DataMax> findSimpleList(DataMax dataMax){
            return dataMaxService.findSimpleList(dataMax);
        }

    采用spring默认生成key策略

    生成的key:zwh:hahaDataMax{id=null, dataType=null, maxSort=null, createDate=null, updateDate=null, deleteStatus=null}

    RedisTemplate配置,RedisUtils工具类封装使用

    RedisTemplate是Spring对redis操作的封装类。

    RedisAutoConfiguration 这个redis自动配置类主要用来配置RedisTemplate,默认也是使用JdkSerializationRedisSerializer 序列化,需要自定义

    package com.zwh.config;
    
    import com.fasterxml.jackson.annotation.JsonTypeInfo;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisOperations;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    import java.net.UnknownHostException;
    
    /**
     * @author monkey
     * @date 2020/7/10 15:41
     **/
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(RedisOperations.class)
    @EnableConfigurationProperties(RedisProperties.class)
    public class RedisConfig {
    
        /**
         * 默认会覆盖spring auto的默认redisTemplate 即 默认jdk序列化的bean
         * org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
         *
         * @param redisConnectionFactory
         * @return
         */
        @Bean
        @Primary
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            //设置序列化
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            ObjectMapper om = new ObjectMapper();
            // 所有属性都可见,包括私有的,但是没有get set方法的字段也会实例化
    //        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            //序列化时允许非常量字段均输出类型,序列化时输出类型,为了反序列化时使用
            om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                    ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
            // ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
            jackson2JsonRedisSerializer.setObjectMapper(om);
    
            // 配置redisTemplate
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
    
            RedisSerializer stringSerializer = new StringRedisSerializer();
            // key序列化
            redisTemplate.setKeySerializer(stringSerializer);
            // value序列化
            redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
            // Hash key序列化
            redisTemplate.setHashKeySerializer(stringSerializer);
            // Hash value序列化
            redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
            redisTemplate.setConnectionFactory(redisConnectionFactory);
            redisTemplate.afterPropertiesSet();
            return redisTemplate;
        }
    
        @Bean
        @ConditionalOnMissingBean
        public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
                throws UnknownHostException {
            StringRedisTemplate template = new StringRedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }
    }
    View Code
        @RequestMapping("/testRedisTemplate")
        @ResponseBody
        public Object testRedisTemplate(DataMax dataMax) throws JsonProcessingException {
            ValueOperations<String, Object> redisString = template.opsForValue();
            List<DataMax> list = dataMaxService.findSimpleList(dataMax);
            // SET key value: 设置指定 key 的值
            redisString.set("testList", list);
            // GET key: 获取指定 key 的值
            Map<String,Object> map = new HashMap<>();
            map.put("testList",redisString.get("testList"));return map;
        }

    直接对查询的列表数据直接set进redis中

    redis中显示的数据格式

    RedisUtils工具类的封装 

    参考资料

    一个走心的REDISUTIL工具类https://www.freesion.com/article/4679386590/
    Redis和springboot 整合redisUtil类
    https://www.cnblogs.com/yui66/p/9935927.html
    
    RedisUtil工具类
    https://www.cnblogs.com/jpfss/p/10812032.html
    RedisUtil工具类
    https://blog.csdn.net/liuxiao723846/article/details/50401406
    package com.zwh.common.data.redis;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Component;
    import org.springframework.util.CollectionUtils;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
    
    /**
     * redis 工具类
     * @Author Scott
     *
     */
    @Component
    public class RedisUtil {
    
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
    
        /**
         * 指定缓存失效时间
         * 
         * @param key  键
         * @param time 时间(秒)
         * @return
         */
        public boolean expire(String key, long time) {
            try {
                if (time > 0) {
                    redisTemplate.expire(key, time, TimeUnit.SECONDS);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 根据key 获取过期时间
         * 
         * @param key 键 不能为null
         * @return 时间(秒) 返回0代表为永久有效
         */
        public long getExpire(String key) {
            return redisTemplate.getExpire(key, TimeUnit.SECONDS);
        }
    
        /**
         * 判断key是否存在
         * 
         * @param key 键
         * @return true 存在 false不存在
         */
        public boolean hasKey(String key) {
            try {
                return redisTemplate.hasKey(key);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 删除缓存
         * 
         * @param key 可以传一个值 或多个
         */
        @SuppressWarnings("unchecked")
        public Long del(String... key) {
            if (key != null && key.length > 0) {
                if (key.length == 1) {
                    Boolean isDel = redisTemplate.delete(key[0]);
                    if(isDel!=null && isDel) {
                        return 1L;
                    }
                } else {
                    return redisTemplate.delete(CollectionUtils.arrayToList(key));
                }
            }
            return 0L;
        }
    
        // ============================String=============================
        /**
         * 普通缓存获取
         * 
         * @param key 键
         * @return*/
        public Object get(String key) {
            return key == null ? null : redisTemplate.opsForValue().get(key);
        }
    
        /**
         * 普通缓存放入
         * 
         * @param key   键
         * @param value 值
         * @return true成功 false失败
         */
        public boolean set(String key, Object value) {
            try {
                redisTemplate.opsForValue().set(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 普通缓存放入并设置时间
         * 
         * @param key   键
         * @param value 值
         * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
         * @return true成功 false 失败
         */
        public boolean set(String key, Object value, long time) {
            try {
                if (time > 0) {
                    redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
                } else {
                    set(key, value);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 普通缓存放入并设置时间
         *
         * @param key
         * @param value
         * @param time
         * @param timeType 时间类型
         * @return
         */
        public boolean set(String key, Object value, long time, TimeUnit timeType) {
            try {
                if (time > 0) {
                    redisTemplate.opsForValue().set(key, value, time, timeType);
                } else {
                    set(key, value);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 递增
         * 
         * @param key 键
         * @param delta  要增加几(大于0)
         * @return
         */
        public long incr(String key, long delta) {
            if (delta < 0) {
                throw new RuntimeException("递增因子必须大于0");
            }
            return redisTemplate.opsForValue().increment(key, delta);
        }
    
        /**
         * 递减
         * 
         * @param key 键
         * @param delta  要减少几(小于0)
         * @return
         */
        public long decr(String key, long delta) {
            if (delta < 0) {
                throw new RuntimeException("递减因子必须大于0");
            }
            return redisTemplate.opsForValue().increment(key, -delta);
        }
    
        // ================================Map=================================
        /**
         * HashGet
         * 
         * @param key  键 不能为null
         * @param item 项 不能为null
         * @return*/
        public Object hget(String key, String item) {
            return redisTemplate.opsForHash().get(key, item);
        }
    
        /**
         * 获取hashKey对应的所有键值
         * 
         * @param key 键
         * @return 对应的多个键值
         */
        public Map<Object, Object> hmget(String key) {
            return redisTemplate.opsForHash().entries(key);
        }
    
        /**
         * HashSet
         * 
         * @param key 键
         * @param map 对应多个键值
         * @return true 成功 false 失败
         */
        public boolean hmset(String key, Map<String, Object> map) {
            try {
                redisTemplate.opsForHash().putAll(key, map);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * HashSet 并设置时间
         * 
         * @param key  键
         * @param map  对应多个键值
         * @param time 时间(秒)
         * @return true成功 false失败
         */
        public boolean hmset(String key, Map<String, Object> map, long time) {
            try {
                redisTemplate.opsForHash().putAll(key, map);
                if (time > 0) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 向一张hash表中放入数据,如果不存在将创建
         * 
         * @param key   键
         * @param item  项
         * @param value 值
         * @return true 成功 false失败
         */
        public boolean hset(String key, String item, Object value) {
            try {
                redisTemplate.opsForHash().put(key, item, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 向一张hash表中放入数据,如果不存在将创建
         * 
         * @param key   键
         * @param item  项
         * @param value 值
         * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
         * @return true 成功 false失败
         */
        public boolean hset(String key, String item, Object value, long time) {
            try {
                redisTemplate.opsForHash().put(key, item, value);
                if (time > 0) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 删除hash表中的值
         * 
         * @param key  键 不能为null
         * @param item 项 可以使多个 不能为null
         */
        public void hdel(String key, Object... item) {
            redisTemplate.opsForHash().delete(key, item);
        }
    
        /**
         * 判断hash表中是否有该项的值
         * 
         * @param key  键 不能为null
         * @param item 项 不能为null
         * @return true 存在 false不存在
         */
        public boolean hHasKey(String key, String item) {
            return redisTemplate.opsForHash().hasKey(key, item);
        }
    
        /**
         * hash递增 如果不存在,就会创建一个 并把新增后的值返回
         * 
         * @param key  键
         * @param item 项
         * @param by   要增加几(大于0)
         * @return
         */
        public double hincr(String key, String item, double by) {
            return redisTemplate.opsForHash().increment(key, item, by);
        }
    
        /**
         * hash递减
         * 
         * @param key  键
         * @param item 项
         * @param by   要减少记(小于0)
         * @return
         */
        public double hdecr(String key, String item, double by) {
            return redisTemplate.opsForHash().increment(key, item, -by);
        }
    
        // ============================set=============================
        /**
         * 根据key获取Set中的所有值
         * 
         * @param key 键
         * @return
         */
        public Set<Object> sGet(String key) {
            try {
                return redisTemplate.opsForSet().members(key);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 根据value从一个set中查询,是否存在
         * 
         * @param key   键
         * @param value 值
         * @return true 存在 false不存在
         */
        public boolean sHasKey(String key, Object value) {
            try {
                return redisTemplate.opsForSet().isMember(key, value);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 将数据放入set缓存
         * 
         * @param key    键
         * @param values 值 可以是多个
         * @return 成功个数
         */
        public long sSet(String key, Object... values) {
            try {
                return redisTemplate.opsForSet().add(key, values);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    
        /**
         * 将set数据放入缓存
         * 
         * @param key    键
         * @param time   时间(秒)
         * @param values 值 可以是多个
         * @return 成功个数
         */
        public long sSetAndTime(String key, long time, Object... values) {
            try {
                Long count = redisTemplate.opsForSet().add(key, values);
                if (time > 0) {
                    expire(key, time);
                }
                return count;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    
        /**
         * 获取set缓存的长度
         * 
         * @param key 键
         * @return
         */
        public long sGetSetSize(String key) {
            try {
                return redisTemplate.opsForSet().size(key);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    
        /**
         * 移除值为value的
         * 
         * @param key    键
         * @param values 值 可以是多个
         * @return 移除的个数
         */
        public long setRemove(String key, Object... values) {
            try {
                Long count = redisTemplate.opsForSet().remove(key, values);
                return count;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
        // ===============================list=================================
    
        /**
         * 获取list缓存的内容
         * 
         * @param key   键
         * @param start 开始
         * @param end   结束 0 到 -1代表所有值
         * @return
         */
        public List<Object> lGet(String key, long start, long end) {
            try {
                return redisTemplate.opsForList().range(key, start, end);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 获取list缓存的长度
         * 
         * @param key 键
         * @return
         */
        public long lGetListSize(String key) {
            try {
                return redisTemplate.opsForList().size(key);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    
        /**
         * 通过索引 获取list中的值
         * 
         * @param key   键
         * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
         * @return
         */
        public Object lGetIndex(String key, long index) {
            try {
                return redisTemplate.opsForList().index(key, index);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 将list放入缓存
         * 
         * @param key   键
         * @param value 值
         * @return
         */
        public boolean lSet(String key, Object value) {
            try {
                redisTemplate.opsForList().rightPush(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 将list放入缓存
         * 
         * @param key   键
         * @param value 值
         * @param time  时间(秒)
         * @return
         */
        public boolean lSet(String key, Object value, long time) {
            try {
                redisTemplate.opsForList().rightPush(key, value);
                if (time > 0) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 将list放入缓存
         * 
         * @param key   键
         * @param value 值
         * @return
         */
        public boolean lSet(String key, List<Object> value) {
            try {
                redisTemplate.opsForList().rightPushAll(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 将list放入缓存
         * 
         * @param key   键
         * @param value 值
         * @param time  时间(秒)
         * @return
         */
        public boolean lSet(String key, List<Object> value, long time) {
            try {
                redisTemplate.opsForList().rightPushAll(key, value);
                if (time > 0) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 根据索引修改list中的某条数据
         * 
         * @param key   键
         * @param index 索引
         * @param value 值
         * @return
         */
        public boolean lUpdateIndex(String key, long index, Object value) {
            try {
                redisTemplate.opsForList().set(key, index, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 移除N个值为value
         * 
         * @param key   键
         * @param count 移除多少个
         * @param value 值
         * @return 移除的个数
         */
        public long lRemove(String key, long count, Object value) {
            try {
                Long remove = redisTemplate.opsForList().remove(key, count, value);
                return remove;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    }
    View Code
  • 相关阅读:
    Spring boot mvn
    软考
    java
    webserver代理生成本地类的两种方式
    行转列语句,记录一下
    React.PureComponent浅比较理解
    关于职业规划和职场规则以及未来发展发方向
    程序员的一天
    代码commit规范
    element UI 使用总结
  • 原文地址:https://www.cnblogs.com/gne-hwz/p/13343589.html
Copyright © 2011-2022 走看看