错误场景
java代码中设置了rediskey,但redis客户端查询不到,redis中设置该key,结果java中读取为null
问题发现
实际存储在redis中key多了一串\xAC\xED\x00\x05t\x00\x011乱码,导致客户端查询不出来。
问题原因
- spring-data-redis的RedisTemplate<K, V>模板类在操作redis时默认使用JdkSerializationRedisSerializer来进行序列化。没有使用StringRedisSerializer对key做序列化处理
- JdkSerializationRedisSerializer会导致redis中保存的key和value可读性较差,出现一些不可读的16进制字符
解决方案一
重新注册一下redisTemplate的bean
因为redis的redisTemplate的注册方式为@ConditionalOnMissingBean,如果程序中没定义则使用redis的template,如果有则使用程序本身的template,
@Configuration
public class RedisConfig {
@Value("${spring.redis.port}")
private Integer port;
@Value("${spring.redis.database}")
private Integer database;
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.password}")
private String password;
@Bean(name = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate(){
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory(host,port,password,database));
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 设置值(value)的序列化采用Jackson2JsonRedisSerializer。
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// 设置键(key)的序列化采用StringRedisSerializer。
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
private RedisConnectionFactory connectionFactory(String hostName, int port, String password, int database) {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setPort(port);
redisStandaloneConfiguration.setDatabase(database);
redisStandaloneConfiguration.setHostName(hostName);
redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
JedisConnectionFactory factory = new JedisConnectionFactory(redisStandaloneConfiguration,
JedisClientConfiguration.builder().build());
return factory;
}
}
解决方案二
实例化redisTemplate的时候添加泛型,这样读取的时候会默认使用StringRedisSerializer
例如:RedisTemplate<String, String>