解决redisTemplate向redis中插入String类型数据时出现乱码问题

 更新时间:2023年12月20日 14:52:16   作者:起名好难(# #)  
这篇文章主要介绍了解决redisTemplate向redis中插入String类型数据时出现乱码问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

前置知识

1.啥是redisTemplate?

redisTemplate是SpringDataRedis中的一个工具类,封装了各种对Redis的操作,并将不同数据类型的操作API封装到了不同的类型中

举例:

下面的语句表示将【"name","谷歌"】这个k-v存入到redis中

redisTemplate.opsForValue().set("name","谷歌");

2.啥是序列化和反序列化?

序列化:将对象存入一个文件的过程。

反序列化:从一个文件中解析出对象。

问题描述

首先,这是一个Springboot+SpringDataRedis的项目

如果按照【前置知识】的例子中那样写,那么存入redis的将会是二进制数据,格式如下:

实际上这并不属于啥错误,将上面的二进制转化成String后,其实就是“谷歌”。

但这样可读性很差,且占用过多内存。

成因分析

省流:由于没有给自定义序列化方式,所以默认采用的是jdk序列化器进行序列化,导致最后存入的数据是二进制。

以下是详细分析过程:

这是如何调用redisTemplate并实现插入数据的一段代码:

@SpringBootTest
class SpringDataRedisDemoApplicationTests {
 
    @Resource
    private RedisTemplate redisTemplate;
 
    @Test
    void testString() {
        // 写入String数据
        redisTemplate.opsForValue().set("name","谷歌");
    }
 
}

其中set方法的入参数据类型为两个Object。

RedisTemplate可以接收任意Object作为值写入Redis

当没有自定义序列化方式时,默认会使用jdk序列化器,redisTemplate的源码中做了下面的定义:

public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
 
	@Override
	public void afterPropertiesSet() {
        ...
		if (defaultSerializer == null) {
 
			defaultSerializer = new JdkSerializationRedisSerializer(
					classLoader != null ? classLoader : this.getClass().getClassLoader());
		}
        ...
    }
}
   

jdk序列化器在底层会将Java对象转成字节进行存储,也就是之前看到的二进制数据。

解决方案

1.改什么?

redisTemplate的源码中其实规定了5种序列化器,其中四种默认均为null。

public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
 
	private @Nullable RedisSerializer<?> defaultSerializer;
	private @Nullable RedisSerializer keySerializer = null;
	private @Nullable RedisSerializer valueSerializer = null;
	private @Nullable RedisSerializer hashKeySerializer = null;
	private @Nullable RedisSerializer hashValueSerializer = null;
}

那么只要能改变序列化的方式,就能改变存入redis的数据类型。

RedisSerializer这个接口的实现类有下面几种:

对于key一般使用 StringRedisSerializer  ; (key一般是字符串)

而对于value一般使用 GenericJackson2JsonRedisSerializer 。(value可能是复杂的对象)

2.怎么改?

可以通过【配置类注入容器】来实现对序列化器的修改

@Configuration
public class RedisConfig {
 
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
        //创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //设置连接工厂
        template.setConnectionFactory(connectionFactory);
        //创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        //设置key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        //设置value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashKeySerializer(jsonRedisSerializer);
        //返回
        return template;
    }
}

在注入redisTemplate对象时,指定其泛型为<String,Object>

@SpringBootTest
class SpringDataRedisDemoApplicationTests {
 
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
 
 
    @Test
    void testString() {
        // 写入String数据
        redisTemplate.opsForValue().set("name","百度");
        // 获取String数据
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println(name);
    }
 
}

3.报错怎么办?

可能会报下面的错

Caused by: java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder
    at stu.demo.springdataredisdemo.config.RedisConfig.redisTemplate(RedisConfig.java:20)

引入下面的依赖即可

<!--Jackson-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot集成ElaticJob定时器的实现代码

    SpringBoot集成ElaticJob定时器的实现代码

    这篇文章主要介绍了SpringBoot集成ElaticJob定时器的实现代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • SpringBoot集成JWT实现Token登录验证的示例代码

    SpringBoot集成JWT实现Token登录验证的示例代码

    随着技术的发展,分布式web应用的普及,通过session管理用户登录状态成本越来越高,因此慢慢发展成为token的方式做登录身份校验,本文就来介绍一下SpringBoot集成JWT实现Token登录验证的示例代码,感兴趣的可以了解一下
    2023-12-12
  • Springcloud之Gateway组件详解

    Springcloud之Gateway组件详解

    Spring Cloud Gateway是Spring Cloud微服务生态下的网关组件。Spring Cloud Gateway是基于Spring 5和Spring Boot 2搭建的,本质上是一个Spring Boot应用。本文详细介绍了SpringCloud的网关组件 Gateway,,需要的朋友可以参考下
    2023-05-05
  • 详解重试框架Spring retry实践

    详解重试框架Spring retry实践

    spring retry是从spring batch独立出来的一个能功能,主要实现了重试和熔断。这篇文章主要介绍了详解重试框架Spring retry实践,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • Scala中如何中断循环详解

    Scala中如何中断循环详解

    在Scala中,可以使用break和continue语句来中断循环。break语句可以在满足某个条件时中断循环,而continue语句可以在满足某个条件时跳过当前循环迭代,直接执行下一次迭代
    2023-04-04
  • Springboot视频接口报大量的ClientAbortException找不到原因的解决

    Springboot视频接口报大量的ClientAbortException找不到原因的解决

    本文主要介绍了Springboot视频接口报大量的ClientAbortException找不到原因的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-08-08
  • java生成jar包并且单进程运行的实例

    java生成jar包并且单进程运行的实例

    下面小编就为大家分享一篇java生成jar包并且单进程运行的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • JDK10新特性之var泛型和多个接口实现方法

    JDK10新特性之var泛型和多个接口实现方法

    这篇文章主要介绍了JDK10的新特性:var泛型和多个接口实现方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • SpringBoot解决mysql连接8小时问题

    SpringBoot解决mysql连接8小时问题

    服务连接mysql数据库,8小时没有数据库的操作时候,数据库会主动断开连接释放资源,本文就详细的介绍一下解决方法,感兴趣的可以了解一下
    2023-08-08
  • SpringCloud对服务内某个client进行单独配置的操作步骤

    SpringCloud对服务内某个client进行单独配置的操作步骤

    我们的微服务项目用的是springCloud,某个微服务接口因为数据处理量大,出现了接口超时的情况,我们需要单独修改这一个feignClient的超时时间,所以本文介绍了SpringCloud对服务内某个client进行单独配置的操作步骤,需要的朋友可以参考下
    2023-10-10

最新评论