Springboot整合redis+cacheSprin

这是我参与更文挑战的第2天,活动详情查看: 更文挑战

Springboot整合redis +cache

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.依赖

 <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
 </dependency>
复制代码

其他依赖fastjson

<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.60</version>
</dependency>
复制代码

2.application.properties配置

#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.测试

@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

<!--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>
复制代码

配置

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

2. 构建domain和dao

对象需要序列化

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

复制代码

3. 测试redis

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

 @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

@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);
    }
复制代码

其他方法

//设置过期时间
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接口,使用方便

测试

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

在这里插入图片描述
redis数据库成功存入,但是存入的是字节数组。

配置转换成json

@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;

    }

}

复制代码

查看数据库,已成功转换。
在这里插入图片描述