原因分析
原因与RedisTemplate源码中的默认序列化方式有关
1defaultSerializer = new JdkSerializationRedisSerializer( 2 classLoader != null ? classLoader : this.getClass().getClassLoader());`
默认序列化使用的是JdkSerializationRedisSerializer,我们进去看看
1 public JdkSerializationRedisSerializer(ClassLoader classLoader) { 2 this(new SerializingConverter(), new DeserializingConverter(classLoader)); 3 }
可以看到这里使用了SerializingConverter对象,再进去看看,
这里的convert方法就是这个对象传入JdkSerializationRedisSerializer后会被调用的方法
1public byte[] convert(Object source) { 2 ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1024); 3 4 try { 5 this.serializer.serialize(source, byteStream); 6 return byteStream.toByteArray(); 7 } catch (Throwable var4) { 8 throw new SerializationFailedException("Failed to serialize object using " + this.serializer.getClass().getSimpleName(), var4); 9 } 10 }
可以看出来这里使用普通的serializer的serialize方法,并没有什么特别的
但是问题就在于,这里的source是Object对象,
JdkSerializationRedisSerializer把传入的值当Object对象进行序列化,所以可以猜测这里key出现的\xac\xed\x00\x05t\x00\tb其实可能是对象头信息。
解决方案
我们可以使用下面这种方法设置其他序列化方式,这样就不会出现问题:
1redisTemplate.setKeySerializer(new StringRedisSerializer()); 2redisTemplate.setValueSerializer(new StringRedisSerializer()); 3redisTemplate.setHashKeySerializer(new StringRedisSerializer()); 4redisTemplate.setHashValueSerializer(new StringRedisSerializer());
但是这种方法明显很不优雅,所以我们应该直接使用StringRedisTemplate类来解决问题:
1@Autowired 2private StringRedisTemplate stringRedisTemplate;
它帮我们进行了设置序列化方式的封装,我们可以看看它的构造方法:
1public StringRedisTemplate() { 2 RedisSerializer<String> stringSerializer = new StringRedisSerializer(); 3 setKeySerializer(stringSerializer); 4 setValueSerializer(stringSerializer); 5 setHashKeySerializer(stringSerializer); 6 setHashValueSerializer(stringSerializer); 7 }
当然也可以使用配置的方式设置序列化方法,不过这里就不作出说明了。