Springboot整合redis +cache

2022-05-12 11:25:06 浏览数 (1)

文章目录
  • redis简介

  • springboot整合redis
    • 1.依赖
    • 2.application.properties配置
    • 3.测试
    • 使用mysql数据库 测试
      • 上面我使用了*StringRedisTemplate* ,在使用数据库测试时,我使用的是*RedisTemplate*,关联和区别?
      • redistemplate 主要方法:
    • springboot cache redis
    • 扩展
      • **使用fastjson序列化**
      • **注解方式实现过期时间自定义**
      • 参考:
redis简介

redis(Remote Dictionary Server 远程数据服务) 是一个高性能的key-value数据库。

Redis 与其他 key - value 缓存产品有以下三个特点:

Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。

Redis不仅仅支持简单的key-value类型的数据,同时还提供string、hash、list、set、sorted set等数据结构的存储。

Redis支持数据的备份,即master-slave模式的数据备份。

springboot整合redis

1.依赖
代码语言:javascript复制
 <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
 </dependency>

其他依赖fastjson

代码语言:javascript复制
<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.60</version>
</dependency>
2.application.properties配置
代码语言:javascript复制
#Redis
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=192.168.4.100
# Redis服务器连接端口
spring.redis.port=6379
# Redis密码
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=5000
3.测试
代码语言:javascript复制
@RestController
public class RedisTestCtrl {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @PostMapping("/user")
    public Object addUser(@RequestBody User user) {
        stringRedisTemplate.opsForValue().set("user", JSON.toJSONString(user));
        return "success";
    }

    @GetMapping("/user")
    public User getUser() {
        return JSON.parseObject(stringRedisTemplate.opsForValue().get("user"), User.class);
    }

    @PostMapping("/users")
    public Object addUsers(@RequestBody List<User> users) {
        stringRedisTemplate.opsForList().rightPushAll("users", users.stream().map(JSON::toJSONString).collect(Collectors.toList()));
        return "success";
    }

    @GetMapping("/users")
    public Object getUsers() {
        List<User> users = new ArrayList<>();
        while (true) {
            User user = JSON.parseObject(stringRedisTemplate.opsForList().leftPop("users"), User.class);
            if (Objects.isNull(user)) {
                break;
            }
            users.add(user);
        }
        return users;
    }
}

上面已将数据存入redis,可使用redis可视化工具进行查看

使用mysql数据库 测试

1. 添加mybatis,mysql 依赖, 配置连接 pom

代码语言:javascript复制
<!--mybatis and mysql-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.0</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

配置

代码语言:javascript复制
#mysql
spring.datasource.url=jdbc:mysql://192.168.4.100:3306/test
spring.datasource.username=root
spring.datasource.password=123456

2. 构建domain和dao

对象需要序列化

代码语言:javascript复制
@Data
public class User implements Serializable {
    private String name;
    private int age;
}
代码语言:javascript复制
@Mapper
public interface UserDao {
    @Select("select * from RedisUser")
    List<User> userList();
}

3. 测试redis 重点

检测缓存中是否有该key的缓存,没有则从数据库获取数据写入缓存

代码语言:javascript复制
 @GetMapping("/queryUsers")
    public List<User> queryUsers() {
    	//自定义一个key,根据需求
        String key = "data";
        ValueOperations<String, List<User>> operations = redisTemplate.opsForValue();
        boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey) {
            List<User> users = operations.get(key);
            System.out.println("==========从缓存中获得数据=========");
            return users;
        } else {
            List<User> users = userDao.userList();
            System.out.println("==========从数据表中获得数据=========");
            // 写入缓存,设置过期时间
            operations.set(key, users, 5, TimeUnit.SECONDS);
            return users;
        }
    }

set()方法设置缓存过期时间,可不设置

到此就已经完成了redis的测试

上面我使用了StringRedisTemplate ,在使用数据库测试时,我使用的是RedisTemplate,关联和区别?

如图, user键是使用StringRedisTemplate data键是使用RedisTemplate 在RedisDesktop 可视化工具中看出,使用StringRedisTemplate维护的数据,键和值都是String形式,方便维护; 而使用RedisTemplate维护的数据,键和值都是转换为字节数组形式,没有可读性。 建议:字符串形式数据可以使用StringRedistemplate,对象形式数据可以使用RedisTemplate,如果使用StringRedisTemplate则需要转换成对象,如上面使用fastjson转换成user对象。

RedisTemplate和StringRedisTemplate的区别:

  1. 两者的关系是StringRedisTemplate继承RedisTemplate。
  2. 两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。
  3. SDR默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。

StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。

RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。

redistemplate 主要方法:

上面测试时只使用了redisteplate的opsForValue()方法和hasKey()方法;

redistemplate 方法有很多,图上只是一部分,

redis有5种数据类型,String,list,hash,set,zset ,相应的有对应的ops方法

下面举例list类型对应的opsForLIst

代码语言:javascript复制
@RequestMapping(value = "/redis/list")
    public void listOperation() {
        List<String> list1 = new ArrayList<String>();
        list1.add("a1");
        list1.add("a2");
        list1.add("a3");

        List<String> list2 = new ArrayList<String>();
        list2.add("b1");
        list2.add("b2");
        list2.add("b3");
        //leftpush是在list的左侧添加,即列表的头部,right是在list的左侧添加,即在列表的尾部。
        // 插入
        redisTemplate.opsForList().leftPush("listkey1",list1);
        redisTemplate.opsForList().rightPush("listkey2", list2);
        
        //获取数据后移除,Pop方法会移除缓存
        List<String> resultList1 = (List<String>) redisTemplate.opsForList().leftPop("listkey1");
        List<String> resultList2 = (List<String>) redisTemplate.opsForList().rightPop("listkey2");
        System.out.println("resultList1:"   resultList1);
        System.out.println("resultList2:"   resultList2);
    }

其他方法

代码语言:javascript复制
//设置过期时间
redistemplate.expire(key,seconds,TimeUnit.SECONDS)
//如果只想要查看某个元素。可以使用range,他有三个参数,第一个参数是key,后面是搜索范围,
//全集合搜索可以用(key,0,-1);
redisTemplate.opsForList().range("listkey1",0,-1)

其余类型方法暂略。

springboot cache redis

上面我们已经整合了springboot redis ,可以使用cache进一步简化。 springboot 默认集成了cache,注解使用即可。

SpringCache包含两个顶级接口,Cache(缓存)和CacheManager(缓存管理器), 而在spring-boot-starter-data-redis中已经帮我们自动配置实现了Cache接口,使用方便

测试

代码语言:javascript复制
 @GetMapping("/getUser")
    @Cacheable(cacheNames = "aa",key = "#p0")
    public User addUser(String id) {
        log.info("进入数据");
        User user = new User("xiaomi", 19);
        return user;
    }

redis数据库成功存入,但是存入的是字节数组。

配置转换成json

代码语言:javascript复制
@Configuration
public class MyRedisConfig {

    public MyRedisConfig() {
    }

    /**
     * 参考RedisAutoConfiguration, 主动缓存调用的时候  转JSON
     */
    @Bean
    public RedisTemplate<Object, User> userRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {


        RedisTemplate<Object, User> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);

        Jackson2JsonRedisSerializer<User> serializer = new Jackson2JsonRedisSerializer<User>(User.class);
        template.setDefaultSerializer(serializer);
        return template;
    }


    /**
     * 参考 org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration;
     * <p>
     * 被动缓存调用的时候  结果转JSON
     */
    @Bean
    public RedisCacheManager userCacheManage(RedisConnectionFactory connectionFactory) {
        
        Jackson2JsonRedisSerializer<Object> redisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        redisSerializer.setObjectMapper(objectMapper);

        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer));

        RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory).cacheDefaults(cacheConfiguration).build();

        return redisCacheManager;

    }

}

查看数据库,已成功转换。

扩展
使用fastjson序列化

springboot2.x使用redis作为缓存(使用fastjson序列化的方式,并调试反序列化异常)

注解方式实现过期时间自定义

springboot2.0整合redis自定义注解实现过期时间

git地址:https://gitee.com/yutiankong/springcache_redis

0 人点赞