原文:https://blog.csdn.net/skymouse2002/article/details/80736577

redis的客户端换成了spring-boot-starter-data-redis,碰到了一个奇怪的问题,

在同一个方法中

1.先hset,再hget,正常获得数据。

在不同的方法中 先hset,再hget获取不到数据,通过redis的monitor监控发现了命令的问题:

实际我的key为JK_HASH:csrk,hashkey为user,但是根据上图所示,实际执行的命令多了好多其他字符,这是什么原因呢?

在服务器端先确认发现实际有这个Hash,通过hset可以得到正确的数据,所以第一次执行hset的时候命令是正常的,问题可能出现在hget上面,先打开源码看一下

@SuppressWarnings("unchecked")
public HV get(K key, Object hashKey) {
final byte[] rawKey = rawKey(key);
final byte[] rawHashKey = rawHashKey(hashKey); byte[] rawHashValue = execute(new RedisCallback<byte[]>() { public byte[] doInRedis(RedisConnection connection) {
return connection.hGet(rawKey, rawHashKey);
}
}, true); return (HV) deserializeHashValue(rawHashValue);
}

从这里可以看到实际上传给redis的都是byte数据,而byte数组是rawKey和rawHashKey生成的,先看下rawKey方法

@SuppressWarnings("unchecked")
byte[] rawKey(Object key) {
Assert.notNull(key, "non null key required");
if (keySerializer() == null && key instanceof byte[]) {
return (byte[]) key;
}
return keySerializer().serialize(key);
}

然后进一步跟踪keySerializer()方法

RedisSerializer keySerializer() {
return template.getKeySerializer();
}
public RedisSerializer<?> getKeySerializer() {
return keySerializer;
}

最后跟踪到是RedisTemplate中的属性keySerializer导致的,而通过打印keySerializer的class发现 默认使用的是org.springframework.data.redis.serializer.JdkSerializationRedisSerializer,但它是如何进行初始化的呢,默认的构造函数中并没有对该属性进行初始化。

根据RedisTemplate的类关系发现它是继承RedisAccessor的,而此类是实现的org.springframework.beans.factory.InitializingBean接口,这个接口有个特性,凡是继承该接口的类,在初始化bean的时候会执行afterPropertiesSet方法。

而afterPropertiesSet方法中,确实对keySerializer进行了初始化:

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<K>(this);
}
initialized = true;
}

在这里可以看到默认使用的正是org.springframework.data.redis.serializer.JdkSerializationRedisSerializer,而问题正在这里,通过查询可以发现序列化器有这些,而在这里我们需要使用的是StringRedisSerializer

加入如下代码:

@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;
}

最新文章

  1. 假如 UNION ALL 里面的子句 有 JOIN ,那个执行更快呢
  2. Caffe初试(二)windows下的cafee训练和测试mnist数据集
  3. java中 sleep 与 wait 的区别
  4. 浅谈C++虚函数
  5. phpcms上线步骤,无法生成缓存,页面空白原因
  6. OC补充
  7. 中国气象台api
  8. Hibernate的映射文件中基于主键的双向1对1的关联
  9. 201521123111《Java程序设计》第7周学习总结
  10. Java常用类(五)之集合工具类Collections
  11. Maven 设置Maven源/镜像
  12. bzoj 2500 幸福的道路 树上直径+set
  13. 【深度学习篇】---CNN和RNN结合与对比,实例讲解
  14. ABAQUS/CAE——Context
  15. redo/declare/typeset
  16. 引用变量 php面试总结1
  17. Visual Studio 2017 配置导出/导入/重置
  18. 找不到phpize
  19. Json 简记
  20. gitlab4.0备份还原

热门文章

  1. 【WAP触屏】YouKu视频弹窗播放组件
  2. Python3之调试
  3. SQL Server数据同步到Oracle
  4. Vue 项目中的ESlint语法报错问题
  5. 2019年Java面试题基础系列228道(6)
  6. 模型-视图-控制器的C++解释
  7. mysql 库、表、数据的增删改
  8. Span复习
  9. 微信开发核心AccessToken实现
  10. Wine 总结