文章目录
- ⛄概述
- ⛄快速入门
- ❄️❄️导入依赖
- ❄️❄️配置文件
- ❄️❄️测试代码
- ⛄数据化序列器
- ⛄StringRedisTemplate
- ⛄RedisTemplate的两种序列化实践方案总结
⛄概述
SpringData
是Spring
中数据操作的模块,包含对各种数据库的集成,其中对Redis
的集成模块就叫做SpringDataRedis
,官网地址:https://spring.io/projects/spring-data-redis
- 提供了对不同Redis客户端的整合(Lettuce和Jedis)
- 提供了RedisTemplate统一API来操作Redis
- 支持Redis的发布订阅模型
- 支持Redis哨兵和Redis集群
- 支持基于Lettuce的响应式编程
- 支持基于JDK.JSON.字符串.Spring对象的数据序列化及反序列化
- 支持基于Redis的JDKCollection实现
SpringDataRedis
中提供了RedisTemplate
工具类,其中封装了各种对Redis
的操作。并且将不同数据类型的操作API封装到了不同的类型中:
redisTemplate
可以操作一些通用命令.
⛄快速入门
SpringBoot
已经提供了对SpringDataRedis
的支持,使用非常简单:
❄️❄️导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.7</version><relativePath/> <!-- lookup parent from repository --></parent><name>redis-demo</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><!--redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--common-pool--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!--Jackson依赖--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>
❄️❄️配置文件
spring:redis:host: ipport: 6379password: 密码lettuce:pool:max-active: 8 #最大连接max-idle: 8 #最大空闲连接min-idle: 0 #最小空闲连接max-wait: 100ms #连接等待时间
❄️❄️测试代码
@SpringBootTest
class RedisDemoApplicationTests {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Testvoid testString() {// 写入一条String数据redisTemplate.opsForValue().set("name", "mayun");// 获取string数据Object name = redisTemplate.opsForValue().get("name");System.out.println("name = " + name);}
}
⛄数据化序列器
RedisTemplate
可以接收任意Object
作为值写入Redis:
只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:
缺点:
- 可读性差
- 内存占用较大
可以自定义如下配置:
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){// 创建RedisTemplate对象RedisTemplate<String, Object> template = new RedisTemplate<>();// 设置连接工厂template.setConnectionFactory(connectionFactory);// 创建JSON序列化工具GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();// 设置Key的序列化template.setKeySerializer(RedisSerializer.string());template.setHashKeySerializer(RedisSerializer.string());// 设置Value的序列化template.setValueSerializer(jsonRedisSerializer);template.setHashValueSerializer(jsonRedisSerializer);// 返回return template;}
}
这里采用了JSON序列化来代替默认的JDK序列化方式。最终结果如图:
图略。
整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。
不过,其中记录了序列化时对应的 class 名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。
⛄StringRedisTemplate
尽管之前 JSON 的序列化方式可以满足我们的需求,但依然存在一些问题,如下:
{"Class": "com.snow.Student","name": "wang","age": 18
}
为了在反序列化时知道对象的类型,JSON序列化器会将类的 class 类型写入json结果中,存入Redis,会带来额外的内存开销。
为了减少内存的消耗,我们可以采用手动序列化的方式,换句话说,就是不借助默认的序列化器,而是我们自己来控制序列化的动作,同时,我们只采用String的序列化器,这样,在存储value时,我们就不需要在内存中就不用多存储数据,从而节约我们的内存空间
这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate
,它的key和value的序列化方式默认就是String方式。省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用:
@SpringBootTest
class RedisStringTests {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testvoid testString() {// 写入一条String数据stringRedisTemplate.opsForValue().set("verify:phone:13600008888", "124143");// 获取string数据Object name = stringRedisTemplate.opsForValue().get("name");System.out.println("name = " + name);}private static final ObjectMapper mapper = new ObjectMapper();@Testvoid testSaveUser() throws JsonProcessingException {// 创建对象User user = new User("mayun", 21);// 手动序列化String json = mapper.writeValueAsString(user);// 写入数据stringRedisTemplate.opsForValue().set("user:200", json);// 获取数据String jsonUser = stringRedisTemplate.opsForValue().get("user:200");// 手动反序列化User user1 = mapper.readValue(jsonUser, User.class);System.out.println("user1 = " + user1);}
}
此时我们再来看一看存储的数据,小伙伴们就会发现那个class数据已经不在了,节约了我们的空间~
{"name": "wang","age": 18
}
⛄RedisTemplate的两种序列化实践方案总结
RedisTemplate
的两种序列化实践方案:
方案一:
自定义 RedisTemplate
修改 RedisTemplate
的序列化器为 GenericJackson2JsonRedisSerializer
会占用额外的内存空间 记录字节码
方案二:
使用 StringRedisTemplate
写入 Redis 时,手动把对象序列化为 JSON
读取 Redis 时,手动把读取到的 JSON 反序列化为对象