redis乱码

在项目中使用redis保存数据时,发现 key 和 value 前面都有一串16进制的乱码

image-20210405164824625

原因

RedisTemplate源码如下,可以看出默认使用的是**JdkSerializationRedisSerializer**进行序列化,造成乱码问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private @Nullable RedisSerializer keySerializer = null;
private @Nullable RedisSerializer valueSerializer = null;
private @Nullable RedisSerializer hashKeySerializer = null;
private @Nullable RedisSerializer hashValueSerializer = null;
private RedisSerializer<String> stringSerializer = RedisSerializer.string();

// 其他代码。。。

if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
if (enableDefaultSerializer) {
if (keySerializer == null) {
keySerializer = defaultSerializer;
defaultUsed = true;
}
if (valueSerializer == null) {
valueSerializer = defaultSerializer;
defaultUsed = true;
}
if (hashKeySerializer == null) {
hashKeySerializer = defaultSerializer;
defaultUsed = true;
}
if (hashValueSerializer == null) {
hashValueSerializer = defaultSerializer;
defaultUsed = true;
}
}

解决方法

1、优雅的解决方法

1
2
3
@Autowired
// private RedisTemplate redisTemplate;
StringRedisTemplate redisTemplate; // 优雅地解决Redis乱码问题

StringRedisTemplate类的声明如下,就相当于RedisTemplate<String, String>

1
public class StringRedisTemplate extends RedisTemplate<String, String>

2、设置序列化方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Autowired private RedisTemplate redisTemplate;

/**
* 解决Redis乱码问题
*
* @param redisTemplate
*/
@Autowired(required = false)
public void setRedisTemplate(RedisTemplate redisTemplate) {
RedisSerializer stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setValueSerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
redisTemplate.setHashValueSerializer(stringSerializer);
this.redisTemplate = redisTemplate;
}

第8-16行使用@Autowired标注了setRedisTemplate方法,项目启动的时候会调用该方法,为redisTemplate对象设置了序列化方法。

3、配置类(示例代码使用的Jackson2JsonRedisSerializer)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Configuration
@EnableAutoConfiguration
public class RedisConfig {

@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate redisTemplate = new StringRedisTemplate(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer =
new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 设置完这个可以直接将对象以json格式存入redis中,但是取出来的时候要用JSON.parseArray(Json.toJsonString(object),Object.class)解析一下
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
// 调用后完成设置
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}