入门必备,深入理解Spring Redis Data,源码分析,RedisDesktopManager

文章前言

最近学习了redis缓存,大家刚刚接触redis,可能还停留在会使用阶段,但是对于它得实现原理和底层不够了解,本文主要讲解spring对redis得进行得封装 :Spring Redis Data部分源码分析,如果有讲解不适之处,欢迎指出,先赞后看,已成习惯!!
测试版本 :
spring-boot-starter-data-redis
入门必备,深入理解Spring Redis Data,源码分析,RedisDesktopManager_第1张图片
jedis 3.0.1

入门必备,深入理解Spring Redis Data,源码分析,RedisDesktopManager_第2张图片

1.了解Spring Redis Data

Spring Data支持的其中一个关键值存储是Redis。 官方如下:

Redis是一个高级键值存储库。它类似于memcached数据集不是易变的,值可以是字符串,就像memcached一样,还有列表集和有序集。所有这些数据类型都可以操作使用原子操作来推送/弹出元素,添加/删除元素,执行服务器端联合、交集、集合之间的差异等等。Redis支持不同的排序能力。

Spring Data Redis提供了从Spring应用程序轻松配置和访问Redis的功能。它提供了用于与存储交互的低级和高级抽象,使用户不必再关注基础设施。

2.分析Spring Redis Data

Spring Boot默认为我们配置了JedisConnectionFactory,RestTemplate,StringRedisTemplate,我们可以直接通过配置文件,指定Redis服务器host,port,password,database以及一些连接池,使我们直接在SpringBoot添加Spring-data-redis直接注入RedisTemplateStringRedisTemplate后可以直接进行业务操作了,下面我们看下spring boot得JAR目录
入门必备,深入理解Spring Redis Data,源码分析,RedisDesktopManager_第3张图片
入门必备,深入理解Spring Redis Data,源码分析,RedisDesktopManager_第4张图片
从这几个目录可以看到,SpringBoot为这些常用的框架都多了默认的整合配置,就好比泡面佐料已经配好了,你在需要吃的时候只需要注入热水即可
入门必备,深入理解Spring Redis Data,源码分析,RedisDesktopManager_第5张图片
可以看到在自动配置的类中,引用了spring.data.redis.xxx的实现类,这也是为什么要SpringBoot Data Redis引入依赖的原因.

2.1概念

深了解之前,我们来了解几个具体类得概念:

  1. RedisConnection:提供了Redis通信的核心构建块,因为它处理与Redis后端通信。它还自动将底层连接库异常转换为Spring一致的DAO异常层次结构,这样您就可以在不更改任何代码的情况下切换连接器,因为操作语义保持不变。(翻译自官网解释,其实简单理解下,就是用来连接Redis的
  2. RedisConnectionFactory:是构建RedisConnection的工厂类
  3. RedisStandaloneConfiguration:Redis标准配置,用来构建RedisConnectionFactory须要的必要参数,比如host;port;password
    完整得实现类肯定不止这几个,这边只列出几个核心,我们常用得实现类进行分析

2.2通过自动配置类进行分析

说这么,不如我们来实际操作一下,下面我把我测试得一个配置类列出,通过这个配置类来进行分析
redis-config. properties

# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host-name=111.229.109.245
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=100
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=10000
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=5
# 连接超时时间(毫秒)
spring.redis.timeout=1000000
## 最大连接数
spring.redis.pool.max-total=200
@Configuration
@PropertySource(value = { "classpath:redis-config. properties" })
public class RedisConfig {
    /**
     * 连接池配置信息
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.redis.pool")
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig config = new JedisPoolConfig();
        return config;
    }
    
    /**
     * 2.创建RedisConnectionFactory:配置redis 链接信息
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.redis")
    public RedisConnectionFactory redisConnectionFactory(JedisPoolConfig config) {

        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcf = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration
                .builder();
        // 修改我们的连接池配置
        jpcf.poolConfig(config);
        // 通过构造器来构造jedis客户端配置
        JedisClientConfiguration jedisClientConfiguration = jpcf.build();
        return new JedisConnectionFactory(redisStandaloneConfiguration);
    }

    /**
     *  RedisTemplate(或StringRedisTemplate)虽然已经自动配置,但是不灵活(第一没有序列化,第二泛型为不是我们想要的类型)
     *  所以自己实现RedisTemplate或StringRedisTemplate)
     */
    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        setRedisTemplate(redisTemplate);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        //        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // 设置值(value)的序列化采用FastJsonRedisSerializer。
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        //        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
        // 设置键(key)的序列化采用StringRedisSerializer。
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();
    }
}
  1. 先看最核心的入口类:org.springframework.data.redis.core.RedisTemplate
    RedisTemplate

同样底层是维护了RedisConnectionFactory,在Spring Data
Redis中和RedisCacheManager属于不同的Redis应用模块,RedisCacheManager负责Redis数据缓存的核心实现,RedisTemplate是Spring为方便操作Redis各种命令而封装出来的工具类,其功能类似于jedis,它继承于org.springframework.data.redis.core.RedisAccessor,主要是设置org.springframework.data.redis.connection.RedisConnectionFactory,并在spring bean初始化完毕对connectionFactory进行为空校验;

在上方得配置文件中,我们创建完连接之后,我们又自己实现了RedisTemplate,我们以后得实际应用数据操作都需要通过RedisTemplate来实现
1.2 通过RedisTemplate处理对象
大多数用户可能会使用RedisTemplate及其相应的软件包org.springframework.data.redis.core。 事实上,模板由于其丰富的功能集而成为Redis模块的中心类。 该模板为Redis交互提供了高级抽象。 虽然RedisConnection提供接受和返回二进制值(字节数组)的低级方法,但模板负责序列化和连接管理,使用户无需处理此类详细信息。
此外RedisTemplate提供丰富的,通用的接口,用于处理特定类型或某些密钥(通过KeyBound接口),如下表所示

Interface Description
ValueOperations 简单 K-V 操作
SetOperations set 类型数据操作
ZSetOperations zset 类型数据操作
HashOperations 针对 map 类型的数据操作
ListOperations 针对 list 类型的数据操作

之所以RedisTemplate能够操作数据,是因为它实现了
在这里插入图片描述
RedisOperations(封装了Redis的各种数据操作)

RedisTemplate在其大多数操作中使用基于Java的序列化程序。 这意味着模板编写或读取的任何对象都是通过Java序列化和反序列化的。 您可以更改模板上的序列化机制,Redis模块提供了几个实现,这些实现可以在org.springframework.data.redis.serializer包中找到。

如果你需要把对象存储到redis数据库中,一定要记得实体类实现序列化

  1. 测试
    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    @Test
    void testString() {
        redisTemplate.opsForValue().set("admin", "root");
    }

通过注入RedisTemplate对象,调用RedisOperations接口得方法,来往redis数据库中塞入admin字符串,刚刚说到对象需要序列化,下面我们来聊聊序列化

     Emp user = new Emp();
        user.setAge(11);
        user.setEmail("[email protected]");
        user.setEmpname("test");
        redisTemplate.opsForValue().set("emp1",user);

2.3序列化

从框架的角度来看,存储在Redis中的数据只是字节数。 虽然Redis本身支持各种类型,但在大多数情况下,这些类型指的是数据的存储方式而不是它所代表的方式。 由用户决定信息是否被翻译成字符串或任何其他对象。

在Spring Data中,用户(自定义)类型和原始数据之间的转换在Redis的org.springframework.data.redis.serializer包中处理。
普通的连接使用没有办法把 Java对象直接存入 Redis,而需要我们自己提供方案,这时往往就是将对象序列化,然后使用 Redis 进行存储,而取回序列化的内容后,在通过转换转变为 Java 对象, Spring 模板中提供了封装的方案,在它内部提供了 RedisSerializer 接口(org.spring企amework.data.redis.serializer.RedisSerializer)和一些实现类,如下图:
入门必备,深入理解Spring Redis Data,源码分析,RedisDesktopManager_第6张图片
大家肯定纳闷redis是如何通过把对象转换成二进制,存储,并且当我们需要拿得时候怎么知道哪个指定得对象
下面几种方法实现了RedisSerializer接口:

  • GenericJackson2JsonRedisSerializer:通用的使用 Json2.jar 的包,将 Redis 对象的序 列化器。
  • Jackson2JsonRedisSerializer:通过 Jackson2.jar包提供的序列化进行转换。
  • JdkSerializationRedisSerializer: 使用 JDK 的序列化器进行转化。
  • OxmSerializer,:使用 SpringO/X 对象 Object和 XML相互转换。
  • StringRedisSerializer: 使用字符串进行序列化 。
  • GenericToStringSerializer:通过通用 的字符串序列化进行相互转换。
    使用它们就能够帮助我们把对象通过序列化存储到 Redis 中,也可以把 Redis存储的内容转换为 Java对象,为此 Spring提供的 RedisTemplate还有两个属性
    keySerializer 一键序列器 , valueSerializer 一值序列器
    这样Spring Redis Data知道会用对应 的序列化器去转换 Redis 的键值.

你可能感兴趣的:(入门必备,深入理解Spring Redis Data,源码分析,RedisDesktopManager)