千家信息网

Spring-RedisTemplate写入数据出现乱码怎么解决

发表于:2025-01-24 作者:千家信息网编辑
千家信息网最后更新 2025年01月24日,本篇内容介绍了"Spring-RedisTemplate写入数据出现乱码怎么解决"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大
千家信息网最后更新 2025年01月24日Spring-RedisTemplate写入数据出现乱码怎么解决

本篇内容介绍了"Spring-RedisTemplate写入数据出现乱码怎么解决"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!


问题复现

项目依赖

  org.springframework.boot  spring-boot-starter-web  org.springframework.boot  spring-boot-starter-test  test  org.springframework.boot  spring-boot-starter-data-redis

Redis配置

  • yaml文件配置

spring:  application:    name: booklet-redis  redis:    host: 127.0.0.1    port: 6379    password: adminadmin    timeout: 5000ms
  • Redis配置类

package com.liumapp.booklet.redis.config;import org.springframework.beans.factory.annotation.Autowired;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.*;import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;@Configurationpublic class RedisConfig {    /**     * 注入 RedisConnectionFactory     */    @Autowired    RedisConnectionFactory redisConnectionFactory;    @Bean    public RedisTemplate functionDomainRedisTemplate() {        RedisTemplate redisTemplate = new RedisTemplate<>();        initDomainRedisTemplate(redisTemplate, redisConnectionFactory);        return redisTemplate;    }    /**     * 设置数据存入 redis 的序列化方式     *     * @param redisTemplate     * @param factory     */    private void initDomainRedisTemplate(RedisTemplate redisTemplate, RedisConnectionFactory factory) {        redisTemplate.setKeySerializer(new StringRedisSerializer());        redisTemplate.setHashKeySerializer(new StringRedisSerializer());        redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());        redisTemplate.setConnectionFactory(factory);    }    /**     * 实例化 HashOperations 对象,可以使用 Hash 类型操作     *     * @param redisTemplate     * @return     */    @Bean    public HashOperations hashOperations(RedisTemplate redisTemplate) {        return redisTemplate.opsForHash();    }    /**     * 实例化 ValueOperations 对象,可以使用 String 操作     *     * @param redisTemplate     * @return     */    @Bean    public ValueOperations valueOperations(RedisTemplate redisTemplate) {        return redisTemplate.opsForValue();    }    /**     * 实例化 ListOperations 对象,可以使用 List 操作     *     * @param redisTemplate     * @return     */    @Bean    public ListOperations listOperations(RedisTemplate redisTemplate) {        return redisTemplate.opsForList();    }    /**     * 实例化 SetOperations 对象,可以使用 Set 操作     *     * @param redisTemplate     * @return     */    @Bean    public SetOperations setOperations(RedisTemplate redisTemplate) {        return redisTemplate.opsForSet();    }    /**     * 实例化 ZSetOperations 对象,可以使用 ZSet 操作     *     * @param redisTemplate     * @return     */    @Bean    public ZSetOperations zSetOperations(RedisTemplate redisTemplate) {        return redisTemplate.opsForZSet();    }}

测试代码

package com.liumapp.booklet.redis;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.redis.core.ListOperations;import org.springframework.test.context.junit4.SpringRunner;import javax.annotation.Resource;import java.util.ArrayList;import java.util.List;@SpringBootTest(classes = BookletRedisMain.class)@RunWith(SpringRunner.class)public class BookletRedisMainTest {    @Resource    private ListOperations listOperations;    @Test    public void leftPushTest () {        List list = new ArrayList<>();        list.add("hello world");        listOperations.leftPush("listKey", list);    }}

运行上述测试代码后,我们会在redis中插入一组list类型的数据,其key为listKey,value为只有一个元素的list对象

接下来我们通过redis-cli去获取listKey这个值,可以看到乱码的出现:

127.0.0.1:6379> LRANGE listKey 0 101) "\xac\xed\x00\x05sr\x00\x13java.util.ArrayListx\x81\xd2\x1d\x99\xc7a\x9d\x03\x00\x01I\x00\x04sizexp\x00\x00\x00\x01w\x04\x00\x00\x00\x01t\x00\x0bhello worldx"

当然,这对于我们项目的实际使用没有什么影响,在程序中再次获取listKey也不会出现乱码,只有通过redis-cli等工具直接取值的时候,才会出现乱码

问题出现原因

问题原因在于我们对Redis进行配置的这一段代码(事实上这也是redisTemplate的默认配置代码):

private void initDomainRedisTemplate(RedisTemplate redisTemplate, RedisConnectionFactory factory) {    redisTemplate.setKeySerializer(new StringRedisSerializer());    redisTemplate.setHashKeySerializer(new StringRedisSerializer());    redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());    redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());    redisTemplate.setConnectionFactory(factory);}

在这里,redisTemplate对HashValue和Value的序列化类采用的是JDK默认的序列化策略,而不是String类型的序列化策略,所以我们在redis-cli中看到的value会因为序列化策略的问题,出现乱码

解决办法

将JDK默认的序列化策略更换为String类型的序列化策略

redisTemplate.setHashValueSerializer(new StringRedisSerializer());redisTemplate.setValueSerializer(new StringRedisSerializer());

但是这样做的话,我们在进行存储的时候,也只能存储String类型的数据,所以测试代码要进行如下修改

@Testpublic void leftPushTest () {    List list = new ArrayList<>();    list.add("hello world2");    listOperations.leftPush("listKey", list.toString());}

再一次去redis-cli中取值,得到如下结果:

127.0.0.1:6379> LRANGE listKey 0 101) "[hello world2]"2) "\xac\xed\x00\x05sr\x00\x13java.util.ArrayListx\x81\xd2\x1d\x99\xc7a\x9d\x03\x00\x01I\x00\x04sizexp\x00\x00\x00\x01w\x04\x00\x00\x00\x01t\x00\x0bhello worldx"

可以发现乱码问题已经解决

总结

不建议更换redisTemplate默认的序列化策略,有乱码就让它乱着吧,反正知道正确的解码策略就不会影响程序的正常运行(不过通过php等其他语言去获取redis的值貌似不太好解决)

"Spring-RedisTemplate写入数据出现乱码怎么解决"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0