Redis序列化问题
每当初学者学习Redis,并且使用SpringBoot整合Redis的时候,总会看到别人使用这种东西—配置类,然后自己又看不懂,oh,fuck!!
这是为什么,为什么要有这个配置类???
package com.example.txf_redis.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
//配置redisTemplate
// 默认情况下的模板只能支持 RedisTemplate<String,String>,
// 只能存入字符串,很多时候,我们需要自定义 RedisTemplate ,设置序列化器
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String,Object> template = new RedisTemplate <>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
下面我来发表一下我自己的看法:
1.不用配置类
下面是实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Serializable {
private static final long serialVersionUID = -1;
private Integer id;
private String name;
private String desc;
}
@Data
public class People implements Serializable {
private static final long serialVersionUID = -1;
private Student student;
public People() {
}
public People(Student student) {
this.student = student;
}
private Integer getId() {
return student.getId();
}
private String getName() {
return student.getName();
}
private String getDesc() {
return student.getDesc();
}
}
People对象里面有一个成员叫Student
运行测试,第一个方法,然后去Redis里面查看key
就算我们不用JSON工具,直接插入,同样有问题
@Test
void contextLoads() {
Student student = new Student(1, "田小锋", "爱吃饭");
People people = new People(student);
// redisTemplate.opsForValue().set("user"+student.getId(), JSON.toJSONString(people));
redisTemplate.opsForValue().set("user"+student.getId(),people);
}
为什么Key是那样的呢?不应该只是user1吗?
这就回到了主题了,序列化问题。
因redis默认使用JdkSerializationRedisSerializer来进行序列化,造成key是乱码
原因分析:
spring-data-redis 的 RedisTemplate<K, V>模板类 在操作redis时默认使用JdkSerializationRedisSerializer 来进行序列化。spring操作redis是在jedis客户端基础上
进行的,而jedis客户端与redis交互的时候协议中定义是用byte类型交互,
看到spring-data-redis中RedisTemplate<K, V>在操作的时候k,v是泛型对象,
而不是byte[]类型的,
这样导致的一个问题就是,如果不对RedisTemplate进行设置,
spring会默认采用defaultSerializer = new JdkSerializationRedisSerializer();
这个方法来对key、value进行序列化操作,
JdkSerializationRedisSerializer它使用的编码是ISO-8859-1
来自:https://blog.csdn.net/m4330187/article/details/108091447
总的来看就是编码有问题
2.使用配置类
所以我们需要用一下这个配置类,在开头已经给出了,(不一定要这个一模一样的啊)我们把配置类,重新使用上,再试试
然后发现,存取都没有问题了!