目录
- 1. 介绍
- 2. 使用RedisTemplate
- 2.1 引入依赖
- 2.2 配置Redis
- 2.3 注入RedisTemplate
- 3. RedisSerializer——自定义序列化器
- 4. StringRedisTemplate
1. 介绍
SpringData是Spring中数据操作的模块,包含对各种数据库的集成,而Spring Data Redis 是 Spring Data 大家族的一部分,它提供了从 Spring 应用程序对 Redis 的轻松配置和访问。
SpringDataRedis的特点:
- 提供了对不同 Redis 客户端的整合(Lettuce 和 Jedis);
- 提供了
RedisTemplate
统一API 来操作 Redis; - 支持 Redis 的
发布订阅模型
; - 支持
Redis哨兵和 Redis集群
; - 基于支持
Lettuce 的响应式编程
; - 支持基于 JDK、Json、字符串、Spring对象的数据序列化以及反序列化;
- 支持基于 Redis 的 JDKCollection 实现;
SpringDataRedis 中提供了 RedisTemplate
工具类,其中封装了各种对 Redis 的操作,并且将不同数据类型的操作 API 封装到了不同的类型中:
API | 返回值类型 | 说明 |
redisTemplate.opsForValue() | ValueOperations | 操作String类型数据 |
redisTemplate.opsForHash() | HashOperations | 操作Hash类型数据 |
redisTemplate.opsForSet() | SetOperations | 操作Set类型数据 |
redisTemplate.opsForZSet() | ZSetOperations | 操作SortedSet类型数据 |
redisTemplate | 通用的命令 |
2. 使用RedisTemplate
2.1 引入依赖
<!-- redis依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.2 配置Redis
spring:
redis:
host: 192.168.200.130 # uri
port: 6379 # 端口号
password: 123456 # 密码
database: 0 # 默认为0号库
# 默认连接池为 lettuce,若要使用 jedis,还要引入相关依赖
lettuce:
pool:
max-active: 8 # 最大连接
max-idle: 8 # 最大空闲连接
min-idle: 0 # 最小空闲连接
max-wait: 1000ms # 最大等待时长
2.3 注入RedisTemplate
package com.example.springdataredisdemo02;
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;
import org.springframework.data.redis.core.ValueOperations;
@SpringBootTest
class SpringDataRedisDemo02ApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
void testString() {
ValueOperations valueOperations = redisTemplate.opsForValue();
// 写入数据
valueOperations.set("name", "张三");
// 获取数据
String name = (String) valueOperations.get("name");
System.out.println("name:" + name);
}
}
成功运行:
但在 Redis 图形化界面中会出现 “乱码”:
这是因为 RedisTemplate 默认使用的是 JDK 的序列化器。
3. RedisSerializer——自定义序列化器
RedisTemplate 可以接收任意 Object 作为值写入 Redis,只不过写入前会先把 Object 序列化为字节形式,默认采用 JDK 序列化器,所以以上是 JDK 序列化器将 Object 值序列化后的结果,显然不符合我们的要求。
缺点:
- 可读性差
- 内存占用大
所以,我们不应该使用 JDK序列化器,而应该使用其他序列化器替代默认的序列化器。
RedisSerializer 的实现类:
其中:StringRedisSerializer专门用于将字符串序列化,因此十分适用于 RedisTemplate 的 key;
GenericJackson2JsonRedisSerializer适用于对象的序列化,因此适用于 RedisTemplate 的 value。
所以,这里我们需要自定义设置序列化器:
package com.example.config;
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.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
@Configuration
public class RedisConfig {
/**
* 在该方法中自定义RedisTemplate的序列化器,方法名自己取,记得加@Bean注解返回RedisTemplate对象
* @param redisConnectionFactory 连接工厂,Spring会自动注入
* @return RedisTemplate对象
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 创建 RedisTemplate 对象
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 设置连接工厂
template.setConnectionFactory(redisConnectionFactory);
// 创建JSON序列化工具
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 设置KEY的序列化
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
// 设置VALUE的序列化
template.setValueSerializer(genericJackson2JsonRedisSerializer);
template.setHashValueSerializer(genericJackson2JsonRedisSerializer);
// 返回
return template;
}
}
然后,进行下测试:
package com.example.springdataredisdemo02;
import com.example.pojo.User;
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;
import org.springframework.data.redis.core.ValueOperations;
@SpringBootTest
class SpringDataRedisDemo02ApplicationTests {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 测试 String 数据类型
*/
@Test
void testString() {
ValueOperations valueOperations = redisTemplate.opsForValue();
// 写入数据
valueOperations.set("name", "张三");
// 获取数据
String name = (String) valueOperations.get("name");
System.out.println("name:" + name);
}
/**
* 测试 User 对象
*/
@Test
void testUser() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
valueOperations.set("user:100", new User(2000300123L, "张三", 20));
User user = (User) valueOperations.get("user:100");
System.out.println(user);
}
}
String数据类型测试结果:
User 对象测试结果:
4. StringRedisTemplate
尽管 JSON 的序列化方式可以满足我们的要求,但依然存在一些问题:
为了在 反序列化 时知道对象的类型,JSON 序列化器会将类的 class 类型写入 json 结果中,存入 Redis,会带来额外的内存开销。
为了节省内存空间,我们不能存储类的 class 信息,因此 key 与 value 都应该使用 StringRedisSerializer 序列化器,对象提前转化为 json 字符串进行存储,但我们需要手动进行反序列化。
Spring 默认提供了一个 StringRedisTemplate 类
,它的 key 和 value 的序列化方式默认就是 String 方式,省去了我们自定义 RedisTemplate 的过程:
package com.example.springdataredisdemo02;
import com.example.pojo.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
@SpringBootTest
class ApplicationTests {
@Autowired
private StringRedisTemplate stringRedisTemplate;
// jackson中对象转json字符串的工具
private ObjectMapper objectMapper = new ObjectMapper();
/**
* 测试 User 对象
*/
@Test
void testUser() throws JsonProcessingException {
// 创建对象
User user = new User(2000300123L, "张三", 20);
// 手动序列化
String userStr = objectMapper.writeValueAsString(user);
// 操作 string 数据类型
ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
// 写入数据
valueOperations.set("user:100", userStr);
// 获取数据
String s = valueOperations.get("user:100");
// 手动反序列化
User user1 = objectMapper.readValue(s, User.class);
System.out.println(user1);
}
}
测试结果:
总结:
RedisTemplate 的两种序列化方案:
方案一:
- 自定义
RedisTemplate
;- 修改序列化器为
GenericJackson2JsonRedisSerializer
;方案二:
- 使用
StringRedisTemplate
;- 写入 Redis 时,手动将对象转化为JSON字符串;
- 读取 Redis 时,手动将JSON字符串反序列化为对象;
感谢观看!