SpringBoot数据访问——整合Redis

SpringBoot数据访问——整合Redis

文章目录

    • SpringBoot数据访问——整合Redis
      • 0.前言
      • 1.maven依赖
      • 2.前期准备 Redis
      • 3.Spring Boot2.x中Redis的默认配置
      • 4.配置Redis
      • 5.通过RedisTemplate操作Redis
      • 6.Junit单元测试 RedisTemplate
      • 7.自定义RedisTemplate

0.前言

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 非关系型数据库(NoSQL),并提供多种语言的API。

使用场景: 1、热点数据的缓存。2、限时业务的运用,利用这一特性可以运用在限时的优惠活动信息、手机验证码等业务场景。3、计数器相关问题,所以可以运用于高并发的秒杀活动、分布式序列号的生成。4、排行榜相关问题,进行热点数据的排序。 5、分布式锁…等等

1.maven依赖

        
        <dependency>
            <groupId>org.springframework.datagroupId>
            <artifactId>spring-data-redisartifactId>
        dependency>

        
        <dependency>
            <groupId>redis.clientsgroupId>
            <artifactId>jedisartifactId>
        dependency>

Redis客户端常见的有Spring Boot2.x默认的lettuce和jedis,此外还有Jredis,Srp,Redisson。

至于他们的区别,这里就不过多赘述,可参阅别人的博客:

Redis的三个客户端框架比较:Jedis,Redisson,Lettuce

2.前期准备 Redis

这里用Docker准备了MySQL和Redis,可参考:

  • Docker的安装与基本操作详解(基于Centos7.5)

  • Docker——Redis的安装与设置密码运行

3.Spring Boot2.x中Redis的默认配置

RedisAutoConfiguration自动配置类,给我们提供了RedisTemplate和StringRedisTemplate(由于最常用String,默认提供了模板操作类)。

@Configuration(
    proxyBeanMethods = false
)
@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;
    }
}

默认的配置在RedisProperties类中,比如database默认是0,此外host,端口,连接超时时间等都有默认配置,还可以配置redis集群。

@ConfigurationProperties(
    prefix = "spring.redis"
)
public class RedisProperties {
    private int database = 0;
    private String url;
    private String host = "localhost";
    private String password;
    private int port = 6379;
    private boolean ssl;
    private Duration timeout;
    private String clientName;
    private RedisProperties.Sentinel sentinel;
    private RedisProperties.Cluster cluster;
    private final RedisProperties.Jedis jedis = new RedisProperties.Jedis();
    private final RedisProperties.Lettuce lettuce = new RedisProperties.Lettuce();

    public RedisProperties() {
    }
    //...省略
}

查看RedisConnectionFactory源码

public interface RedisConnectionFactory extends PersistenceExceptionTranslator {
    RedisConnection getConnection();

    RedisClusterConnection getClusterConnection();

    boolean getConvertPipelineAndTxResults();

    RedisSentinelConnection getSentinelConnection();
}

可发现Spring-data-redis中提供了一个RedisConnectionFactory接口,通过它可以生成一个RedisConnection接口对象,RedisConnection接口对象是对Redis底层接口的封装。如果使用Redis集群模式连接,RedisConnectionFactory可以生成RedisClusterConnection接口对象。还有RedisSentinelConnection,便是Redis哨兵模式连接。这里就只讨论RedisConnection。

例如客户端为Jedis时,spring便提供了RedisConnection接口实现类JedisConnection去封装原有的Jedis。

后续的RedisTemplate操作模板类便会自动从RedisConnectionFactory工厂中获取连接,根据调用的方法对应执行Redis命令,最后关闭Redis连接,这些都被封装了,并不需要开发者关注Redis连接关闭开启的问题。

4.配置Redis

这里时普通模式,集群模式和哨兵模式可参阅其他博客:

SpringBoot连接Redis (Sentinel模式&Cluster模式)

application.properties格式如下:

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

application.yml格式如下:与上面一一对应对应

#Redis配置
spring:
  redis:
    database: 0
    host: IP
    port: 6379
    password: 密码
    timeout: 3000
    jedis:
      pool:
        max-active: 8
        max-wait: -1ms
        max-idle: 8
        min-idle: 0

5.通过RedisTemplate操作Redis

测试类中测试RedisTemplate,其中提供了很多操作Redis的方法

Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为:

String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。

Redis 命令参考

使用RedisTemplate操作5种数据类型:opsFor即可,之后链式调用具体的方法即可:

        redisTemplate.opsForValue() //操作String类型
        redisTemplate.opsForList() //操作List列表
        redisTemplate.opsForSet() //操作set集合
        redisTemplate.opsForHash() //操作Hash
        redisTemplate.opsForZSet() //操作Zset(有序集合)

本文更多的是记录整合步骤,具体的RedisTemplate用法可参阅:

RedisTemplate用法详解

6.Junit单元测试 RedisTemplate

package com.piao;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class MayflyBlogVueApplicationTests {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Test
    void contextLoads() {
        //保存一个字符串 然后获取并输出只控制台
        redisTemplate.opsForValue().set("num","123");
        System.out.println(redisTemplate.opsForValue().get("num"));
    }

}

控制台输出:

123

redis客户端软件查看:

SpringBoot数据访问——整合Redis_第1张图片

key为num,value为123成功存入Redis,Redis普通模式整合过程便到此结束。

具体的集群/哨兵模式,Redis命令和RedisTemplate相关内容并未详细展开,可参阅

  • SpringBoot连接Redis (Sentinel模式&Cluster模式)

  • Redis 命令参考

  • RedisTemplate用法详解

7.自定义RedisTemplate

redisTemplate.opsForValue().set("myEntity",myEntity);//myEntity自定义的实体类的对象

直接保存对象是抛出异常,无法序列化,

org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.io.NotSerializableException: com.piao.controller.vo.BlogIndexVO

解决方法:实体类实现JDK序列化接口(implements Serializable )

public class MyEntity implements Serializable {
  //...
}

实现该接口后,RedisTemplate便会使用默认的jdk序列化将对象保存,但是使用使用redis命令keys *查看会有乱码:实际的key为myEntity

自定义实现RedisTemplate,指定其序列化配置,可避免乱码问题

参考 https://segmentfault.com/a/1190000018883478

package com.piao.config;


import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
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.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

自定义序列化配置后,存入key为myEntity2的数据,使用redis命令keys *查看key:前后对比如图:

SpringBoot数据访问——整合Redis_第2张图片

你可能感兴趣的:(#,SpringBoot,redis,数据库,java,springboot)