springboot集成redis存对象乱码如何解决

1. 前言

Redis是当前最流行的键值数据存储,是一个基于内存的高性能存储系统,常用于缓存、队列、消息中间件等领域。而SpringBoot是一个基于Spring框架的快速开发框架,可以帮助开发者快速搭建可独立运行的Spring应用程序。SpringBoot集成Redis可以帮助我们更加轻松地使用Redis,极大地提高了开发效率。但有时我们在使用Redis存对象时,会出现乱码的情况,这时就需要一些方法来解决这个问题。

2. 问题描述

在使用SpringBoot集成Redis存储对象时,可能会遇到一些问题。如下所示:

public class User implements Serializable {

private String username;

private String password;

// 省略getter和setter方法

}

@Autowired

private RedisTemplate redisTemplate;

User user = new User();

user.setUsername("张三");

user.setPassword("123456");

redisTemplate.opsForValue().set("user", user);

User result = redisTemplate.opsForValue().get("user");

System.out.println(result.getUsername()); //输出的结果是乱码

当我们使用RedisTemplate存储对象时,有时会出现这样的问题:当我们从Redis中获取这个对象时,其属性值会变为乱码。如上述代码中,我们存入的用户名为"张三",但输出的却是乱码,这是非常不符合我们的预期的,并且非常影响我们使用Redis存储对象。

3. 问题原因

造成这个问题的原因是RedisTemplate的默认序列化器使用的是JdkSerializationRedisSerializer,这个序列化器将Java对象序列化后的结果写入Redis中,不同的操作系统、不同的JVM版本对序列化实现有所不同。因此,在存储和读取时会出现乱码的情况。

4. 解决方案

4.1 自定义序列化器

我们可以自己实现一个序列化器,使用自己的序列化策略,可以避免使用默认的序列化器而出现乱码的问题。首先,我们需要实现一个RedisSerializer接口,根据需要实现其序列化方法和反序列化方法:

public class ObjectRedisSerializer implements RedisSerializer<Object> {

private final Charset charset;

public ObjectRedisSerializer() {

this(Charset.forName("UTF8"));

}

public ObjectRedisSerializer(Charset charset) {

this.charset = charset;

}

@Override

public byte[] serialize(Object t) throws SerializationException {

try {

ByteArrayOutputStream byteStream = new ByteArrayOutputStream();

ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteStream);

objectOutputStream.writeObject(t);

objectOutputStream.flush();

objectOutputStream.close();

return byteStream.toByteArray();

} catch (IOException e) {

throw new SerializationException(e.getMessage(), e);

}

}

@Override

public Object deserialize(byte[] bytes) throws SerializationException {

if (bytes == null || bytes.length == 0) {

return null;

}

try {

ByteArrayInputStream byteStream = new ByteArrayInputStream(bytes);

ObjectInputStream objectInputStream = new ObjectInputStream(byteStream);

return objectInputStream.readObject();

} catch (IOException e) {

throw new SerializationException(e.getMessage(), e);

} catch (ClassNotFoundException e) {

throw new SerializationException(e.getMessage(), e);

}

}

}

我们将Java对象序列化成二进制数据保存在Redis中,再将保存的二进制数据反序列化成对象。这样即使不同的操作系统、不同的JVM实现也可以正常序列化,避免了乱码的问题。使用自定义的序列化器:

RedisTemplate redisTemplate = new RedisTemplate<>();

RedisSerializer<String> stringSer = new StringRedisSerializer();

RedisSerializer<Object> objectSer = new ObjectRedisSerializer();

redisTemplate.setKeySerializer(stringSer);

redisTemplate.setValueSerializer(objectSer);

redisTemplate.setHashKeySerializer(stringSer);

redisTemplate.setHashValueSerializer(objectSer);

redisTemplate.setConnectionFactory(redisConnectionFactory);

redisTemplate.afterPropertiesSet();

4.2 使用JSON序列化器

除了自定义序列化器,我们还可以使用更加简单的方式:使用Jackson序列化器,将对象转换成JSON字符串存储到Redis中,然后再将JSON字符串转换成Java对象。这种方式十分简单,而且Jackson序列化器是很常用的工具,别的地方也可以使用。

我们需要添加Jackson相关依赖:

implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.3'

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.12.3'

implementation 'com.fasterxml.jackson.module:jackson-module-parameter-names:2.12.3'

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.12.3'

配置自定义的RedisTemplate:

@Bean

public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {

RedisTemplate redisTemplate = new RedisTemplate<>();

redisTemplate.setConnectionFactory(redisConnectionFactory);

redisTemplate.setKeySerializer(new StringRedisSerializer(Charset.forName("UTF-8")));

redisTemplate.setHashKeySerializer(new StringRedisSerializer(Charset.forName("UTF-8")));

redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

redisTemplate.afterPropertiesSet();

return redisTemplate;

}

5. 总结

使用SpringBoot集成Redis存储对象时,乱码是一个比较常见的问题。我们可以通过自定义序列化器或使用JSON序列化器来避免这个问题。具体需要根据实际情况来选择合适的解决方案。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。

数据库标签