美文网首页
SpringBoot集成Cache缓存(Redis缓存,Redi

SpringBoot集成Cache缓存(Redis缓存,Redi

作者: 木木与呆呆 | 来源:发表于2021-09-14 14:51 被阅读0次

    1.说明

    SpringBoot集成Redis缓存,
    首先创建一个Spring Boot工程,
    使用Maven向导方式创建:
    SpringBoot集成Maven工程
    然后引入redis的spring boot starter,
    演示RedisTemplate的基本用法。

    需要注意的是,
    在SpringBoot1.x使用的是Jedis,
    在SpringBoot2.x使用的是Lettuce。
    下面演示的版本是SpringBoot2.x,
    但是只使用RedisTemplate无需关注Lettuce。

    2.新增pom依赖

    修改pom.xml文件
    增加spring-boot-starter-data-redis依赖,
    以及Redis连接池commons-pool2依赖:

    <!-- spring redis starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
    <!-- spring2.X集成redis所需common-pool2 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
    </dependency>
    

    3.新增Redis配置类

    新增配置类RedisConfig.java,
    用于创建RedisTemplate实例,
    注意设置Key和Value的序列化方式,
    这样Redis保存的就是JSON格式的数据,
    而不是看不懂的JDK序列化数据:

    package com.yuwen.spring.demo.config;
    import org.springframework.cache.annotation.CachingConfigurerSupport;
    import org.springframework.cache.annotation.EnableCaching;
    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.GenericJackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    @EnableCaching
    @Configuration
    public class RedisConfig extends CachingConfigurerSupport {
    
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(factory);
    
            // 设置key序列化方式
            StringRedisSerializer stringSerializer = new StringRedisSerializer();
            template.setKeySerializer(stringSerializer);
            // 设置value序列化方式
            GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();
            template.setValueSerializer(jsonSerializer);
    
            // 初始化,并且填充参数默认值
            template.afterPropertiesSet();
            return template;
        }
    }
    

    另外说下RedisTemplate的自动配置,
    在RedisAutoConfiguration类中自动生成了
    一个RedisTemplate和一个StringRedisTemplate,
    但是RedisTemplate的泛型是<Object,Object>,
    并且没有设置key及value的序列化方式,
    不方便编码,需要编写类型转换的代码,
    所以自定义了一个泛型为<String,Object>的RedisTemplate,
    后面的代码就是注入这个RedisTemplate来使用的,
    由于@ConditionalOnMissingBean注解的作用,
    Spring容器中已经有了RedisTemplate对象,
    这个自动配置类的RedisTemplate不会被实例化。

    4.使用RedisTemplate

    在业务类UserSortControllerImpl.java中,
    使用Spring自动注入RedisTemplate<String, Object>,
    这个业务使用Redis的Zset对用户进行排序,
    按照用户的id存入Redis的有序集合,
    然后按照id从小到大批量查询用户数据,
    并且可以指定id开始和结束范围:

    package com.yuwen.spring.demo.controller.impl;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Set;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.ZSetOperations;
    import org.springframework.web.bind.annotation.RestController;
    import com.google.common.collect.Lists;
    import com.yuwen.spring.demo.controller.UserSortController;
    import com.yuwen.spring.demo.entity.User;
    
    @RestController
    public class UserSortControllerImpl implements UserSortController {
    
        // 保存在Redis中的user集合的key
        private static final String ZSET_USER = "zset_user";
    
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
    
        @Override
        public void createUser(User user) {
            ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
            // 重复添加相同的user会覆盖
            zset.add(ZSET_USER, user, user.getId());
            System.out.println("add user " + user + "to redis zset_user");
        }
    
        @Override
        public List<User> getAllUser(Integer min, Integer max) {
            ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
    
            // 如果边界为空,使用负无穷和正无穷填充
            if (min == null) {
                min = Integer.MIN_VALUE;
            }
    
            if (max == null) {
                max = Integer.MAX_VALUE;
            }
    
            Set<Object> userObjects = zset.rangeByScore(ZSET_USER, min, max);
            System.out.println("getAllUser users=" + userObjects);
    
            List<User> users = Lists.transform(new ArrayList<>(userObjects), object -> (User) object);
    
            return users;
        }
    }
    

    注意RedisTemplate的泛型不能写错,
    否则Spring无法注入对应的单例,
    createUser方法把用户存入Redis,并使用Id作为排序参数,
    getAllUser方法按照ID访问从Redsi查询数据。

    5.Object集合转换问题

    getAllUser方法从Redis查询用户信息时,
    返回的是Set<Object>类型,
    需要转换成List<User>类型返回,
    由于存入的类型一定是User,
    所以Object一定能强转为User:

    Set<Object> userObjects = zset.rangeByScore(ZSET_USER, min, max);
    List<User> users = Lists.transform(new ArrayList<>(userObjects), object -> (User) object);
    

    上面使用了Google Guava的Lists进行转换的,
    需要在pom中增加如下依赖:

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>30.1.1-jre</version>
    </dependency>
    

    6.查看Redis数据

    登录Redis服务端,
    查看存储在zset_user中的数据,
    并且输出其关联的id:

    127.0.0.1:6379> zrange zset_user 0 -1 withscores
    1) "{\"@class\":\"com.yuwen.spring.demo.entity.User\",\"id\":2,\"name\":\"tom\",\"birthday\":null,\"email\":null}"
    2) "2"
    3) "{\"@class\":\"com.yuwen.spring.demo.entity.User\",\"id\":3,\"name\":\"jack\",\"birthday\":null,\"email\":null}"
    4) "3"
    5) "{\"@class\":\"com.yuwen.spring.demo.entity.User\",\"id\":7,\"name\":\"sam\",\"birthday\":null,\"email\":null}"
    6) "7"
    

    可以看到输出的数据是能够看懂的,
    携带其类名的JSON格式。

    7.实体类User说明

    Demo中使用的User.java源码如下:

    package com.yuwen.spring.demo.entity;
    import java.io.Serializable;
    import java.util.Date;
    
    public class User implements Serializable {
        private static final long serialVersionUID = -3301999810945119126L;
    
        private Long id;
    
        private String name;
    
        private Date birthday;
    
        private String email;
    
        @Override
        public String toString() {
            return "User [id=" + id + ", name=" + name + ", birthday=" + birthday + ", email=" + email + "]";
        }
    }
    

    由于在RedisConfig.java中,
    设置了RedisTemplate的value序列化方式为JSON,
    JSON格式不要求实体类实现Serializable,
    但是使用默认的JDK格式,
    一定要实现序列化接口,
    否则数据无法存储到Redis。

    8.参考文章

    springboot集成redis (Lettuce)
    【深入浅出SpringBoot】RedisTemplate使用方法归纳

    相关文章

      网友评论

          本文标题:SpringBoot集成Cache缓存(Redis缓存,Redi

          本文链接:https://www.haomeiwen.com/subject/ibucgltx.html