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