目录:
问题描述:
项目场景:
背景:在java中使用Redis存储String类型的数据时,会出现乱码。
问题描述
例如:在java中创建RedisTemplate操作String类型的数据存储时,会出现乱码,如下代码,
我写了一条存储key为name,值为虎哥的字符串。
然后获取一下这个key为name的值,打印得到的值
package com.sxy.redis;
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;
@SpringBootTest
class SpringDataRedisDemoApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
// 写入一条String数据
redisTemplate.opsForValue().set("name", "虎哥");
// 获取String数据
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name=" + name);
}
}
我们可以看到出现了乱码问题:这里不单单是值出现了乱码,而且key也有乱码问题
原因分析:
Redis的序列化分析:
因为SpringDataRedis的功能可以接收任何类型的对象,可以帮我们将java对象转成Redis可处理的字节,所以我们存进去的 name和虎哥 都被当成了java对象,而redisTemplate的底层,默认对这些对象得处理方式就是利用JDK的序列化工具,ObjectOutPutStream
进入redisTemplate我们发现了四个属性的值都是对应的数据的序列化
这里我们发现上面四个属性的值的,都是下面这个方法定义的默认的jdk的序列化器
通过断点调试redisTemplate.opsForValue().set("name", "虎哥");我们可以发现,进入了JdkSerializationRedisSerializer的类中
最后进入了这里,可以看到有ObjectOutputStream来写对象,这个流的作用就是把java对象转换为字节进行writeObject进行写入
所以我们看到的值就是这样子的数据
缺点:
- 可读性差
- 内存占用较大
解决方案:
我们可以通过修改RedisTemplate的序列化来实现数据乱码问题。
RedisSerializer有一些实现类
这里会有两个我们需要用到的
- StringRedisSerializer
- 如果我的key和hash可以是字符串的情况下就用它
- GenericJackson2JsonRedisSerializer
- 如果我的值是对象就用它
上代码:
代码如下,写了一个配置类注册Bean对象给spring容器管理
package com.sxy.redis.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 {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
// 创建RedisTemplate对象
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 设置连接工厂
template.setConnectionFactory(redisConnectionFactory);
// 创建JSON序列化工具
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 设置key的序列化为 = String
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
// 设置value的序列化为 = GenericJackson2JsonRedisSerializer
template.setValueSerializer(genericJackson2JsonRedisSerializer);
template.setHashValueSerializer(genericJackson2JsonRedisSerializer);
// 返回
return template;
}
}
注意:如果这里运行的话会报错为如下:
Caused by: java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonProcessingException
这是个明显的错误,告诉我们用了如下这个JSON序列化类没有引入jackson的依赖才报错
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer =
new GenericJackson2JsonRedisSerializer();
我们只需要添加如下依赖即可
<!-- Jackson依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
随后我们尝试对其进行写入和读取数据,发现key和value都是正常的显示
总结:
直接在java中使用RedisTemplate模板进行写入字符串数据时会出现,key和value都是乱码问题,
我们修改了RedisTemplate默认的序列化器StringRedisSerializer即可解决此问题。
如果有其他问题:欢迎在下方评论区留言。各位博友,点赞+评论+收藏呗。