Java中Redis存储String类型会有乱码的问题及解决方案
作者:树若逝花若殇
项目场景:
背景:在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即可解决此问题。
到此这篇关于Java中Redis存储String类型会有乱码的文章就介绍到这了,更多相关java redis存储乱码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!