今天遇到一個奇怪的bug,就是redisTemplate獲取不到值,而stringRedisTemplate可以獲取得到,執(zhí)行代碼就是以下
System.out.println(redisTemplate.opsForValue().get("name1"));
System.out.println(stringRedisTemplate.opsForValue().get("name1"));
debug打斷點(diǎn)跟進(jìn)去,DefaultValueOperations.java
public V get(Object key) {
return execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
//此處打開Evaluate Expression工具,計算rawKey.length=="name".getBytes().length,返回結(jié)果為false,可以定位問題在編碼問題上
return connection.get(rawKey);
}
}, true);
}
繼續(xù)debugger,可以到以下AbstractOperations.java
// utility methods for the template internal methods
abstract class ValueDeserializingRedisCallback implements RedisCallback<V> {
private Object key;
public ValueDeserializingRedisCallback(Object key) {
this.key = key;
}
public final V doInRedis(RedisConnection connection) {
//此處是將key序列化為byte[]的,繼續(xù)跟到rawKey方法中
byte[] result = inRedis(rawKey(key), connection);
return deserializeValue(result);
}
@Nullable
protected abstract byte[] inRedis(byte[] rawKey, RedisConnection connection);
}
繼續(xù)跟到rawKey方法
byte[] rawKey(Object key) {
Assert.notNull(key, "non null key required");
//繼續(xù)跟keySerializer()
if (keySerializer() == null && key instanceof byte[]) {
return (byte[]) key;
}
return keySerializer().serialize(key);
}
恭喜找到源頭了,這里獲取的key的序列化對象。
RedisSerializer keySerializer() {
return template.getKeySerializer();
}
推理中,StringRedisTempate可以獲取到值,來看一下這里面的一部分代碼,看看是否有可參考性
public StringRedisTemplate() {
setKeySerializer(RedisSerializer.string());
setValueSerializer(RedisSerializer.string());
setHashKeySerializer(RedisSerializer.string());
setHashValueSerializer(RedisSerializer.string());
}
同理找到RedisTemplate中類似的這段代碼
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
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;
}
}
if (enableDefaultSerializer && defaultUsed) {
Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
}
if (scriptExecutor == null) {
this.scriptExecutor = new DefaultScriptExecutor<>(this);
}
initialized = true;
}
或者可以根據(jù)斷點(diǎn)看到默認(rèn)的Serializer是JdkSerializationRedisSerializer,與StringRedisTemplate中不一致。

image.png
解決:在自定義的RedisConfig中,參考StringRedisTemplate,將對應(yīng)的幾個序列化方法加入。
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(RedisSerializer.string());
template.setValueSerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
template.setHashValueSerializer(RedisSerializer.string());
return template;
}
}