SpringBoot中的Redis仿真实验
一、初始化配置
选用SpringInitializr,填入名称,选择Maven管理
暂时先只勾选两个坐标
创建,pom文件中可以看到这几个坐标
spring-boot-starter-data-redis:设置启动器,利用springboot管理redis(感兴趣的话可以研究一下Jesdis和Lettuce)
lombok:注解开发
二、yml文件配置
因为是本地实验,properties的配置一切从简
三、RedisConfig配置
RedisTemplate返回值是一个泛型类:
其中K
表示键的类型,V
表示值的类型。通过使用泛型,RedisTemplate
可以灵活地支持各种类型的键和值。在很多常见的场景中,键是字符串类型(String
),而值的类型可以是多种多样的(如String
,Integer
,List
等)。为了方便处理不同类型的值,常用的配置是将值类型设为Object
。更方便序列化和反序列化
@Configuration
@Slf4j
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
//日志输出
log.info("加载了redis配置");
//实例化
RedisTemplate<String,Object> redisTemplate=new RedisTemplate<>();
//设置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
//设置序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer());
return redisTemplate;
}
}
整段代码主要就是内容就是实例化了一个Template然后设置连接工厂,最后设置序列化器。
推荐一篇从源码谈RedisSerializer的文章:Redis 序列化器_redis序列化器-CSDN博客
在 RedisTemplate 中设置多种序列化器的原因是为了更灵活地处理不同类型的键和值。
//Value Serializer(值序列化器):用于序列化 Redis 值的对象。
redisTemplate.setKeySerializer(new StringRedisSerializer());
//Value Serializer(值序列化器):用于序列化 Redis 值的对象。
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//Hash Key Serializer(哈希键序列化器):用于序列化 Redis 哈希(hash)类型的键。
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//Hash Value Serializer(哈希值序列化器):用于序列化 Redis 哈希(hash)类型的值。
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
为什么需要这些序列化器(选读):
在 Redis 中,数据是以二进制格式存储的。在 Java 应用程序中,我们通常处理的是对象、字符串等数据类型。为了在 Redis 和 Java 对象之间进行转换,需要序列化和反序列化过程。设置不同的序列化器是为了处理不同类型的数据。
- 键序列化器(Key Serializer):一般来说,Redis 的键通常是字符串,因此使用
StringRedisSerializer
。 - 值序列化器(Value Serializer):如果值是简单的字符串,可以使用
StringRedisSerializer
。但是,如果值是复杂的 Java 对象,使用GenericJackson2JsonRedisSerializer
可以将对象序列化为 JSON 格式存储在 Redis 中,并在读取时自动反序列化为 Java 对象。 - 哈希键序列化器(Hash Key Serializer) 和 哈希值序列化器(Hash Value Serializer):与键值序列化器类似,但是专门用于 Redis 哈希类型的数据。哈希类型的数据可以看作一个键值对集合,键和值都可以是复杂类型,因此使用合适的序列化器非常重要。
当然也有专门提供String类的Template初始化
实际上是底层复写了RedisTemplate<>
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
log.info("开始创建StringRedis模板对象...");
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
// 设置redis的连接工厂对象
stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
return stringRedisTemplate;
}
四、Test1——String类型数据测试
添加pojo类存放序列化数据型
set&get测试
@ExtendWith(SpringExtension.class)
@SpringBootTest
public class RedisStringSetTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
//set测试
@Test
public void testSetStringRedisTemplate() {
// 创建一个User对象
User user = new User("3", "Alice2", 32);
// 将User对象保存到Redis
redisTemplate.opsForValue().set(user.getId(), user);
//60s删除
redisTemplate.opsForValue().set("name","test",1, TimeUnit.MINUTES);
// 从Redis中获取User对象
User retrievedUser = (User) redisTemplate.opsForValue().get(user.getId());
try {
// 验证对象是否被正确保存和检索
assertThat(retrievedUser).isNotNull();
assertThat(retrievedUser.getId()).isEqualTo(user.getId());
assertThat(retrievedUser.getName()).isEqualTo(user.getName());
assertThat(retrievedUser.getAge()).isEqualTo(user.getAge());
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
System.out.println("testSetStringRedisTemplate successfully");
}
}
//get测试
@Test
public void testGetStringRedisTemplate(){
System.out.println(redisTemplate.opsForValue().get("3"));
}
//删除测试
@Test
public void testDeleteStringRedisTemplate(){
redisTemplate.delete("3");
}
//更新测试
@Test
public void testUpdateStringRedisTemplate() {
// 更新键为"3"的数据为新的值,例如 "new_value"
redisTemplate.opsForValue().set("3", "new_value");
}
}
- TTL是倒计时
- 即使两条数据的格式不同也不影响存储
- 重复存储会报错
五、Test2——Hash类型数据测试
@ExtendWith(SpringExtension.class)
@SpringBootTest
public class RedisHashSetTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
public void testHashOperations() {
String hashKey = "user:hash:1";
String field = "user1";
// 创建一个User对象
User user = new User("1", "Alice", 30);
// 将User对象保存到Redis Hash
redisTemplate.opsForHash().put(hashKey, field, user);
// 从Redis Hash中获取User对象
User retrievedUser = (User) redisTemplate.opsForHash().get(hashKey, field);
assertThat(retrievedUser).isNotNull();
assertThat(retrievedUser.getId()).isEqualTo(user.getId());
assertThat(retrievedUser.getName()).isEqualTo(user.getName());
assertThat(retrievedUser.getAge()).isEqualTo(user.getAge());
// 更新User对象
user.setName("Bob");
redisTemplate.opsForHash().put(hashKey, field, user);
// 从Redis Hash中获取更新后的User对象
User updatedUser = (User) redisTemplate.opsForHash().get(hashKey, field);
assertThat(updatedUser).isNotNull();
assertThat(updatedUser.getId()).isEqualTo(user.getId());
assertThat(updatedUser.getName()).isEqualTo("Bob");
assertThat(updatedUser.getAge()).isEqualTo(user.getAge());
// 删除User对象
redisTemplate.opsForHash().delete(hashKey, field);
// 验证User对象已删除
User deletedUser = (User) redisTemplate.opsForHash().get(hashKey, field);
assertThat(deletedUser).isNull();
}
}