• Spring Boot 项目实战(四)集成 Redis


    一、前言

    上篇介绍了接口文档工具 Swagger 及项目监控工具 JavaMelody 的集成过程,使项目更加健壮。在 JAVA Web 项目某些场景中,我们需要用缓存解决如热点数据访问的性能问题,业界常用的中间件如 Memcached 、 Redis 等。相比 Memcached ,Redis 支持更丰富的数据结构。本篇将主要介绍在 Spring Boot 中集成 Redis 的过程。


    二、集成 Redis

    在 Spring Boot 中使用 Redis 有两种方式:

    • 基于 RedisTemplate 类,该类是 Spring Data 提供的工具,可以直接注入使用。
    • 基于 Jedis,Jedis 是 Redis 官方推荐的面向 JAVA 的客户端。

    本文将介绍第一种使用方式。

    2.1 引入依赖包

    其实 Spring Boot 提供的父工程中已经包含了所依赖的 Redis jar 包,我们只需在相应模块引入即可。第一篇我们已经提到过 demo-common 层是公用组件层,那么 Redis 相关的声明及配置应该在该层定义。于是乎在 demo-common 层的 pom 文件中引入 Redis 的依赖包。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    

    2.2 RedisTemplate 的自动配置

    其实我们现在就可以在项目中注入 RedisTemplate 并使用了,至于原因,首先看下「 RedisAutoConfiguration 」类的源码:

    @Configuration
    @ConditionalOnClass({RedisOperations.class})
    @EnableConfigurationProperties({RedisProperties.class})
    @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
    public class RedisAutoConfiguration {
        public RedisAutoConfiguration() {
        }
    
        @Bean
        @ConditionalOnMissingBean(
            name = {"redisTemplate"}
        )
        public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
            RedisTemplate<Object, Object> template = new RedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }
    
        @Bean
        @ConditionalOnMissingBean
        public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
            StringRedisTemplate template = new StringRedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }
    }
    

    从源码可以看出,Spring Boot 会自动帮我们生成了一个 RedisTemplate 及一个 StringRedisTemplate ,但是这个 RedisTemplate 的泛型是 <Object, Object> ,如果我们直接使用就需要处理各种类型转换。所以为了方便使用,我们需要自定义一个泛型为 <String, Object> 的 RedisTemplate 。 而 @ConditionalOnMissingBean 注解的作用是在当前 Spring 上下文中不存在某个对象时,才会自动实例化一个 Bean 。因此我们可以自定义 RedisTemplate 从而替代默认的。

    2.2 自定义 Redis 配置类

    Spring Data 提供了若干个 Serializer ,主要包括:

    • JdkSerializationRedisSerializer — 使用 JAVA 自带的序列化机制将对象序列化为一个字符串
    • OxmSerializer — 将对象序列化为 XML 字符串
    • Jackson2JsonRedisSerializer — 将对象序列化为 JSON 字符串

    其中 RedisTemplate 默认的序列化方式是 Jdk ,虽然是效率比较高但是序列化结果的字符串是最长的。而 JSON 由于其数据格式的紧凑型,序列化结果的字符串是最小的,即占用的内存最小。所以我们选择用 Jackson 替代默认的 Jdk 方式。

    ① 首先在项目父 pom 文件中定义 Jackson 的版本号且声明 Jackson 依赖。

    <properties>
        ...省略其余部分...
        <jackson.version>2.9.4</jackson.version>
    </properties>
    
    <dependencyManagement>
        <dependencies>
            ...省略其余部分...
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.datatype</groupId>
                <artifactId>jackson-datatype-jsr310</artifactId>
                <version>${jackson.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    

    ② 其次在 demo-common 层的 pom 文件中添加上述 Jackson 依赖。

    <dependencies>
        ...省略其余部分...
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
        </dependency>
    </dependencies>
    

    ③ 最后在 demo-common 层创建 com.example.demo.common 包,添加 Redis 目录并在其中创建 RedisConfig 配置类。

    package com.example.demo.common.redis;
    
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.SerializationFeature;
    import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    /**
     * @author linjian
     * @date 2019/3/2
     */
    @Configuration
    public class RedisConfig {
    
        @Bean
        @SuppressWarnings("all")
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            objectMapper.registerModule(new JavaTimeModule());
            objectMapper.findAndRegisterModules();
            objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    
            // 使用 Jackson2JsonRedisSerialize 替换默认序列化
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
    
            StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
            redisTemplate.setConnectionFactory(factory);
            // key 采用 String 的序列化方式
            redisTemplate.setKeySerializer(stringRedisSerializer);
            // hash 的 key 也采用 String 的序列化方式
            redisTemplate.setHashKeySerializer(stringRedisSerializer);
            // value 序列化方式采用 jackson
            redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
            // hash 的 value 序列化方式采用 jackson
            redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
            redisTemplate.afterPropertiesSet();
            return redisTemplate;
        }
    }
    

    2.3 自定义 Redis 工具类

    直接使用 RedisTemplate 操作 Redis 需要很多额外的代码,最好封装成一个工具类,使用时直接注入。 ① 定义一个常用的缓存时间常量类

    package com.example.demo.common.redis;
    
    /**
     * @author linjian
     * @date 2019/3/2
     */
    public class CacheTime {
    
        /**
         * 缓存时效 5秒钟
         */
        public static int CACHE_EXP_FIVE_SECONDS = 5;
    
        /**
         * 缓存时效 1分钟
         */
        public static int CACHE_EXP_MINUTE = 60;
    
        /**
         * 缓存时效 5分钟
         */
        public static int CACHE_EXP_FIVE_MINUTES = 60 * 5;
    
        /**
         * 缓存时效 10分钟
         */
        public static int CACHE_EXP_TEN_MINUTES = 60 * 10;
    
        /**
         * 缓存时效 15分钟
         */
        public static int CACHE_EXP_QUARTER_MINUTES = 60 * 15;
    
        /**
         * 缓存时效 60分钟
         */
        public static int CACHE_EXP_HOUR = 60 * 60;
    
        /**
         * 缓存时效 12小时
         */
        public static int CACHE_EXP_HALF_DAY = 12 * 60 * 60;
    
        /**
         * 缓存时效 1天
         */
        public static int CACHE_EXP_DAY = 3600 * 24;
    
        /**
         * 缓存时效 1周
         */
        public static int CACHE_EXP_WEEK = 3600 * 24 * 7;
    
        /**
         * 缓存时效 1月
         */
        public static int CACHE_EXP_MONTH = 3600 * 24 * 30 * 7;
    
        /**
         * 缓存时效 永久
         */
        public static int CACHE_EXP_FOREVER = 0;
    }
    

    ② 定义工具类

    package com.example.demo.common.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;
    
    /**
     * @author linjian
     * @date 2019/3/2
     */
    @Component
    public class RedisClient {
    
        @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 ttl(String key) {
            return redisTemplate.getExpire(key, TimeUnit.SECONDS);
        }
    
        /**
         * 判断key是否存在
         *
         * @param key 键
         * @return true 存在 false不存在
         */
        public boolean exists(String key) {
            try {
                return redisTemplate.hasKey(key);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 删除缓存
         *
         * @param key 可以传一个值 或多个
         */
        @SuppressWarnings("unchecked")
        public void del(String... key) {
            if (key != null && key.length > 0) {
                if (key.length == 1) {
                    redisTemplate.delete(key[0]);
                } else {
                    redisTemplate.delete(CollectionUtils.arrayToList(key));
                }
            }
        }
    
        /**
         * 模糊匹配批量删除
         *
         * @param pattern 匹配的前缀
         */
        public void deleteByPattern(String pattern) {
            Set<String> keys = redisTemplate.keys(pattern);
            if (!CollectionUtils.isEmpty(keys)) {
                redisTemplate.delete(keys);
            }
        }
    
        /**
         * 设置指定 key 的值
         *
         * @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 == CacheTime.CACHE_EXP_FOREVER) {
                    redisTemplate.opsForValue().set(key, value);
                } else {
                    redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 获取指定 key 的值
         *
         * @param key 键
         * @return 值
         */
        @SuppressWarnings("unchecked")
        public <T> T get(String key) {
            return key == null ? null : (T) redisTemplate.opsForValue().get(key);
        }
    
        /**
         * 将 key 中储存的数字值递增
         *
         * @param key   键
         * @param delta 要增加几(大于0)
         * @return
         */
        public long incr(String key, long delta) {
            if (delta <= 0) {
                throw new IllegalArgumentException("递增因子必须大于0");
            }
            return redisTemplate.opsForValue().increment(key, delta);
        }
    
        /**
         * 将 key 中储存的数字值递减
         *
         * @param key   键
         * @param delta 要减少几(小于0)
         * @return
         */
        public long decr(String key, long delta) {
            if (delta <= 0) {
                throw new IllegalArgumentException("递减因子必须大于0");
            }
            return redisTemplate.opsForValue().increment(key, -delta);
        }
    
        /**
         * 将哈希表 key 中的字段 field 的值设为 value
         *
         * @param key   键
         * @param field 字段
         * @param value 值
         * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
         * @return true 成功 false失败
         */
        public boolean hset(String key, String field, Object value, long time) {
            try {
                redisTemplate.opsForHash().put(key, field, value);
                if (time != CacheTime.CACHE_EXP_FOREVER) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 同时将多个 field-value (域-值)对设置到哈希表 key 中
         *
         * @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 != CacheTime.CACHE_EXP_FOREVER) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 删除一个或多个哈希表字段
         *
         * @param key   键
         * @param field 字段 可以多个
         */
        public void hdel(String key, Object... field) {
            redisTemplate.opsForHash().delete(key, field);
        }
    
        /**
         * 获取存储在哈希表中指定字段的值
         *
         * @param key   键
         * @param field 字段
         * @return 值
         */
        public <T> T hget(String key, String field) {
            return (T) redisTemplate.opsForHash().get(key, field);
        }
    
        /**
         * 获取在哈希表中指定 key 的所有字段和值
         *
         * @param key 键
         * @return 对应的多个键值
         */
        public Map<Object, Object> hmget(String key) {
            return redisTemplate.opsForHash().entries(key);
        }
    
    
        /**
         * 查看哈希表 key 中,指定的字段是否存在
         *
         * @param key   键
         * @param field 字段
         * @return true 存在 false不存在
         */
        public boolean hexists(String key, String field) {
            return redisTemplate.opsForHash().hasKey(key, field);
        }
    
        /**
         * 获取哈希表中字段的数量
         *
         * @param key 键
         * @return 字段数量
         */
        public long hlen(String key) {
            try {
                return redisTemplate.opsForHash().size(key);
            } catch (Exception e) {
                e.printStackTrace();
                return 0L;
            }
        }
    
        /**
         * 向集合添加一个或多个成员
         *
         * @param key    键
         * @param time   时间(秒)
         * @param values 成员 可以是多个
         * @return 成功个数
         */
        public long sadd(String key, long time, Object... values) {
            try {
                Long count = redisTemplate.opsForSet().add(key, values);
                if (time != CacheTime.CACHE_EXP_FOREVER) {
                    expire(key, time);
                }
                return count;
            } catch (Exception e) {
                e.printStackTrace();
                return 0L;
            }
        }
    
        /**
         * 移除集合中一个或多个成员
         *
         * @param key    键
         * @param values 成员 可以是多个
         * @return 移除的个数
         */
        public long srem(String key, Object... values) {
            try {
                return redisTemplate.opsForSet().remove(key, values);
            } catch (Exception e) {
                e.printStackTrace();
                return 0L;
            }
        }
    
        /**
         * 返回集合中的所有成员
         *
         * @param key 键
         * @return 成员列表
         */
        public <T> Set<T> smembers(String key) {
            try {
                return (Set<T>) redisTemplate.opsForSet().members(key);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 判断 member 元素是否是集合 key 的成员
         *
         * @param key    键
         * @param member 成员
         * @return true 存在 false不存在
         */
        public boolean sismember(String key, Object member) {
            try {
                return redisTemplate.opsForSet().isMember(key, member);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
    
        /**
         * 获取集合的成员数
         *
         * @param key 键
         * @return 成员数
         */
        public long slen(String key) {
            try {
                return redisTemplate.opsForSet().size(key);
            } catch (Exception e) {
                e.printStackTrace();
                return 0L;
            }
        }
    
        /**
         * 在列表头部添加一个值
         *
         * @param key   键
         * @param value 值
         * @param time  时间(秒)
         * @return boolean
         */
        public boolean lpush(String key, Object value, long time) {
            try {
                redisTemplate.opsForList().leftPush(key, value);
                if (time != CacheTime.CACHE_EXP_FOREVER) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 在列表头部添加多个值
         *
         * @param key    键
         * @param values 值
         * @param time   时间(秒)
         * @return boolean
         */
        public boolean lpush(String key, List<Object> values, long time) {
            try {
                redisTemplate.opsForList().leftPushAll(key, values);
                if (time != CacheTime.CACHE_EXP_FOREVER) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 在列表尾部添加一个值
         *
         * @param key   键
         * @param value 值
         * @param time  时间(秒)
         * @return boolean
         */
        public boolean rpush(String key, Object value, long time) {
            try {
                redisTemplate.opsForList().rightPush(key, value);
                if (time != CacheTime.CACHE_EXP_FOREVER) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 在列表尾部添加多个值
         *
         * @param key    键
         * @param values 值
         * @param time   时间(秒)
         * @return boolean
         */
        public boolean rpush(String key, List<Object> values, long time) {
            try {
                redisTemplate.opsForList().rightPushAll(key, values);
                if (time != CacheTime.CACHE_EXP_FOREVER) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 移除列表元素
         *
         * @param key   键
         * @param count 移除多少个
         * @param value 值
         * @return 移除的个数
         */
        public long lrem(String key, long count, Object value) {
            try {
                return redisTemplate.opsForList().remove(key, count, value);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    
        /**
         * 通过索引设置列表元素的值
         *
         * @param key   键
         * @param index 索引
         * @param value 值
         * @return boolean
         */
        public boolean lset(String key, long index, Object value) {
            try {
                redisTemplate.opsForList().set(key, index, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 获取列表指定范围内的元素
         *
         * @param key   键
         * @param start 开始
         * @param end   结束 0 到 -1代表所有值
         * @return 元素列表
         */
        @SuppressWarnings("unchecked")
        public <T> List<T> lrange(String key, long start, long end) {
            try {
                return (List<T>) redisTemplate.opsForList().range(key, start, end);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 通过索引获取列表中的元素
         *
         * @param key   键
         * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
         * @return
         */
        public Object lindex(String key, long index) {
            try {
                return redisTemplate.opsForList().index(key, index);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 获取列表长度
         *
         * @param key 键
         * @return 列表长度
         */
        public long llen(String key) {
            try {
                return redisTemplate.opsForList().size(key);
            } catch (Exception e) {
                e.printStackTrace();
                return 0L;
            }
        }
    
        /**
         * 向有序集合添加一个成员,或者更新已存在成员的分数
         *
         * @param key    键
         * @param time   时间(秒)
         * @param member 成员
         * @param score  分数
         * @return
         */
        public boolean zadd(String key, long time, Object member, double score) {
            try {
                boolean ret = redisTemplate.opsForZSet().add(key, member, score);
                if (time != CacheTime.CACHE_EXP_FOREVER) {
                    expire(key, time);
                }
                return ret;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 移除有序集合中的一个或多个成员
         *
         * @param key    键
         * @param values 值 可以是多个
         * @return 移除的个数
         */
        public long zrem(String key, Object... values) {
            try {
                return redisTemplate.opsForZSet().remove(key, values);
            } catch (Exception e) {
                e.printStackTrace();
                return 0L;
            }
        }
    
        /**
         * 通过索引区间返回有序集合成指定区间内的成员 分数从低到高
         *
         * @param key   键
         * @param start 开始
         * @param end   结束 0 到 -1代表所有值
         * @return 成员集合
         */
        public Set<Object> zrange(String key, long start, long end) {
            try {
                return redisTemplate.opsForZSet().range(key, start, end);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 通过索引区间返回有序集合成指定区间内的成员 分数从高到低
         *
         * @param key   键
         * @param start 开始
         * @param end   结束 0 到 -1代表所有值
         * @return 成员集合
         */
        public Set<Object> zrevrange(String key, long start, long end) {
            try {
                return redisTemplate.opsForZSet().range(key, start, end);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 返回有序集合中某个成员的分数值
         *
         * @param key    键
         * @param member 成员
         * @return 分数值
         */
        public double zscore(String key, Object member) {
            try {
                return redisTemplate.opsForZSet().score(key, member);
            } catch (Exception e) {
                e.printStackTrace();
                return 0.0;
            }
        }
    
        /**
         * 判断有序集合中某个成员是否存在
         *
         * @param key    键
         * @param member 成员
         * @return true 存在 false不存在
         */
        public boolean zexist(String key, Object member) {
            try {
                return null != redisTemplate.opsForZSet().score(key, member);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 获取有序集合的成员数
         *
         * @param key 键
         * @return 成员数
         */
        public long zlen(String key) {
            try {
                return redisTemplate.opsForZSet().size(key);
            } catch (Exception e) {
                e.printStackTrace();
                return 0L;
            }
        }
    }
    

    2.4 添加 Redis 常用配置项

    在 application.properties 文件中的添加 Redis 相关的配置项:

    # 数据库索引(默认为0)
    spring.redis.database = 1
    # 服务器地址
    spring.redis.host = 127.0.0.1
    # 服务器连接端口
    spring.redis.port = 6379
    # 服务器连接密码(默认为空)
    spring.redis.password =
    # 连接池最大阻塞等待时间(使用负值表示没有限制)
    spring.redis.pool.max-wait = -1
    # 连接超时时间(毫秒)
    spring.redis.timeout = 3000 
    # 连接池最大连接数
    spring.redis.jedis.pool.max-active = 8
    # 连接池中的最大空闲连接
    spring.redis.jedis.pool.max-idle = 8
    # 连接池中的最小空闲连接
    spring.redis.jedis.pool.min-idle = 1
    

    2.5 Redis 缓存测试

    ① 首先在 DemoService 中注入 RedisClient ,修改 test 方法将 user 对象以 user:1 为键存放到 Redis 中。

    Redis 开发规范:https://yq.aliyun.com/articles/531067

    package com.example.demo.biz.service.impl;
    
    import com.example.demo.biz.service.DemoService;
    import com.example.demo.common.redis.CacheTime;
    import com.example.demo.common.redis.RedisClient;
    import com.example.demo.dao.entity.UserDO;
    import com.example.demo.dao.mapper.business.UserMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * @author linjian
     * @date 2019/1/15
     */
    @Service
    public class DemoServiceImpl implements DemoService {
    
        @Autowired
        private UserMapper userMapper;
    
        @Autowired
        private RedisClient redisClient;
    
        @Override
        public String test() {
            UserDO user = userMapper.selectById(1);
            redisClient.set("user:1", user, CacheTime.CACHE_EXP_FIVE_MINUTES);
            return user.toString();
        }
    }
    

    ② 之后使用 Redis Desktop Manager 客户端连接 Redis 服务器,选择数据库「 1 」,查看刚存放的缓存。 SpringBoot_4_1.png


    三、结语

    至此 Spring Boot 集成 Redis 的具体步骤介绍完毕,我们自定义了 Redis 的序列化方式,并通过一个简单的例子测试了 Redis 的可用性,相关代码已同步至 GitHub 。

  • 相关阅读:
    eshint的配置
    jsp 或 php 等view之中使用javascript简单处理的使用技巧
    响应式图片,在不同尺寸下切换不同张数
    swiper.js + jquery.magnific-popup.js 实现奇葩的轮播需要
    Websocket 协议的基本使用与示例
    vue手记
    docker 架构
    webpack基本使用
    vue组件、路由、事件
    vue基本使用
  • 原文地址:https://www.cnblogs.com/orzlin/p/10496835.html
Copyright © 2020-2023  润新知