SpringDataRedis项目的学习

Spring 是通过 SpringDataRedis 项目对 Redis 进行支持的,在学习Spring Boot 如何集成并使用 Redis 之前,很有必要先对这个项目研究一番,这样才能更好地在 Spring 中使用 Redis。

引入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <!--不依赖Redis的客户端lettuce-->
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!--引入Redis的客户端驱动jedis-->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

在默认的情况下, spring-boot-starter-data-redis (版本 2.x) 会依赖 Lettuce 的 Redis 客户端驱动,而在一般的项目中,我们会使用 Jedis,所以需要在代码中将其依赖排除并引入Jedis 的依赖,这样就可以使用 Jedis 进行编程了。

SpringDataRedis项目的设计

Java 中与 Redis 连接的驱动有很多种,目前广泛使用的是Jedis, 其他的还有 Lettuce、 Jredis 和Srp。Lettuce 目前使用得比较少,而 Jredis 和 Srp 则已不被推荐使用,在 Spring 中己经被标注@Deprecated。

Spring提供了一个RedisConnectionFactory 接口,通过它可以生成一个RedisConnection接口对象,而RedisConnection 接口对象是对 Redis底层接口的封装。例如,Jedis驱动,Spring会提供 RedisConnection 接口的实现类JedisConnection去封装原有的 Jedis ( redis.clients.jedis.Jedis) 对象。 它们的关系如下所示。
在这里插入图片描述

RedisConnectionFactory

在Spring中是通过RedisConnection接口操作Redis的,而RedisConnection 则对原生的 Jedis 进行封装。要获取 RedisConnection 接口对象, 是通过 RedisConnectionFactory 接口 去生成的,所以第一步要配置的便是这个工厂了,而配置这个工厂主要是配置 Redis 的连接池,对于 连接池可以限定其最大连接数、超时时间等属性。

@Bean(name = "jedisPoolConfig")
@ConfigurationProperties(prefix = "spring.redis.jedis.pool")
public JedisPoolConfig getJedisPoolConfig() {
    JedisPoolConfig poolConfig = new JedisPoolConfig();
    return poolConfig;
}

@Bean(name = "redisConnectionFactory")
@ConfigurationProperties(prefix = "spring.redis")
public RedisConnectionFactory getRedisConnectionFactory() {
    if (this.connectionFactory != null) {
        return this.connectionFactory;
    }
//        创建jedis连接工厂
    JedisConnectionFactory connectionFactory = new JedisConnectionFactory(getJedisPoolConfig());
//        获取单机的Redis配置
//        RedisStandaloneConfiguration standaloneConfiguration = connectionFactory.getStandaloneConfiguration();
    this.connectionFactory = connectionFactory;
    return connectionFactory;
}

这里我们通过一个连接池的配置创建了 RedisConnectionFactory, 通过它就能够创建 RedisConnection接口对象。但是我们在使用一条连接时, 要先从 RedisConnectionFactory 工厂获取,然后在使用完成后还要自己关闭它。 Spring 为了进一步简化开发,提供了 RedisTemplate。

RedisTemplate

可以说 RedisTemplate 是使用得最多的类, 所以它也是 Spring 操作 Redis 的重点内容。 RedisTemplate 是一个强大的类,首先它会自动从 RedisConnectionFactory 工厂中获取连接,然后执行对应的 Redis 命令,在最后还会关闭 Redis 的连接。这些在 RedisTemplate 中都被封装了,所以并不需要开发者关注 Redis 连接的闭合问题。只是为了更好地使用 RedisTemplate, 我们还需要掌握它内部的一些细节。 不过,在使用之前我们需要先创建它。

@Bean(name = "redisTemplate")
public RedisTemplate<Object, Object> initRedisTemplate() {
    RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(getRedisConnectionFactory());
    return redisTemplate;
}

测似代码

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(RedisConfiguration.class);
    RedisTemplate redisTemplate = ctx.getBean(RedisTemplate.class);
    redisTemplate.opsForValue().set("keystr", "redisvalue1");
    redisTemplate.opsForHash().put("hash", "field", "hvalue");
//        Object keyl = redisTemplate.opsForValue().get("keyl");
//        System.out.println(keyl);
//        Object o = redisTemplate.opsForHash().get("hash", "field");
//        System.out.println(o);
}

在这里插入图片描述
可以看到, Redis 存入的并不是像key1这样的字符串,这是怎么回事呢?
首先需要明确如下一点:Redis 是一种基于字符串存储的 NoSQL, 而 Java 是基于对象的语言,对象是无法存储到 Redis 中的,不过 Java提供了序列化机制,只要类实现了java.io.Serializable 接口 ,就代表该类的对象能够进行序列化操作,通过将类对象进行序列化就能够得到二进制的字符串,这样 Redis 就可以将这些类对象以字符串进行存储。 Java 也可以将那些二进制字符串通过反序列化转为对象
根据这个原理, Spring 提供了序列化器的机制,并且实现了几个序列化器。
在这里插入图片描述
对于序列化器, Spring 提供了 RedisSerializer 接口,它有两个方法。

  • serialize
    serialize方法能把那些可以序列化的对象转换为二进制字符串。
  • deserialize
    deserialize方法能够通过反序列化把二进制字符串转换为 Java 对象。

上图中的 JacksonJsonRedisSerializer API 过时,Spring己经不推荐使用了,这里再主要再介绍一下 StringRedisSerializer 和 JdkSerializationRedisSerializer。其中JdkSerializationRedisSerializer 是 RedisTemplate 默认的序列化器,代码中的这个字符串就是被它序列化变为一个比较奇怪的宇符串的。其原理如下。
在这里插入图片描述

RedisTemplate提供的序列化器属性(可选)

在这里插入图片描述
由于之前什么都没有配置,因此它会默认使用JdkSerializationRedisSerializer 对对象进行序列化和反序列化。 这就是上图中得到那些复杂字符串的原因 ,只是这样使用会给我们查询 Redis 数据带来很大的困难。 为了克服这个困难,我们希望 RedisTemplate 可以将 Redis 的键以普通字符串保存。 为了达到这个目的,可以将代码修改为如下。

@Bean(name = "redisTemplate")
public RedisTemplate<Object, Object> initRedisTemplate() {
    RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
//        RedisTemplate 会自动初始化 StringRedisSerializer,所以这里直接获取
    RedisSerializer<String> stringSerializer = redisTemplate.getStringSerializer();
    redisTemplate.setKeySerializer(stringSerializer);
    redisTemplate.setValueSerializer(stringSerializer);
    redisTemplate.setHashKeySerializer(stringSerializer);
    redisTemplate.setHashValueSerializer(stringSerializer);
    redisTemplate.setConnectionFactory(getRedisConnectionFactory());
    return redisTemplate;
}

在这里插入图片描述
Redis 使用得最多的是字符串 ,因此在 SpringDataRedis项目中,还提供了一个 StringRedisTemplate 类,这个类继承自 RedisTemplate,只是提供了字符串的操作而己,对于复杂的 Java 对象还需要自行处理

Spring 对 Redis 数据类型操作的封装

Redis 能够支持7种类型的数据结构,这7种类型是字符串、 散列、列表(链表)、 集合、有序集合、基数和地理位置。为此 Spring 针对每一种数据结构的操作都提供了对应的操作接口。
在这里插入图片描述
它们都可以通过 RedisTemplate 得到,得到的方法也都很简单。

//        获取地理位置操作接口 
        redisTemplate.opsForGeo(); 
//        获取散列操作接口 
        redisTemplate.opsForHash(); 
//        获取基数操作接口 
        redisTemplate.opsForHyperLogLog(); 
//        获取列表操作接口
        redisTemplate.opsForList(); 
//        获取集合操作接口 
        redisTemplate.opsForSet();
//        获取字符串操作接口 
        redisTemplate.opsForValue(); 
//        获取有序集合操作接口 
        redisTemplate.opsForZSet();

这样就可以通过各类的操作接口来操作不同的数据类型了,当然这需要你熟悉 Redis 的各种命令。有时我们可能需要对某一个键值对做连续的操作,例如,有时需要连续操作一个散列数据类型或者列表多次,Spring对其也提供有支持,它提供了对应的 BoundXXXOperations 接口。
在这里插入图片描述
同样的, RedisTemplate 也对获取它们提供了对应的方法。以其中一种数据类型为例:

//获取列表(链表)绑定键操作接口 
redisTemplate.boundListops ("list"); 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值