原文: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;
}

RedisTemplate的key默认序列化器问题的更多相关文章

  1. 深入理解Spring Redis的使用 (二)、RedisTemplate事务支持、序列化

    RedisTemplate api详解 1. RedisTemplate的事务 private boolean enableTransactionSupport = false; private bo ...

  2. 一: DRF web应用框架基础,及序列化器的使用

    ---恢复内容开始--- 一: web 应用模式(有两种) 1: 前后端不分离(前端从后端直接获取数据) 2: 前后端分离 二: api 接口 原因一: 为了在团队内部形成共识.防止个人习惯差异引起的 ...

  3. DRF中的序列化器

    DRF中的序列化器详细应用   视图的功能:说白了就是接收前端请求,进行数据处理 (这里的处理包括:如果前端是GET请求,则构造查询集,将结果返回,这个过程为序列化:如果前端是POST请求,假如要对数 ...

  4. drf之序列化器的使用

    一.序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经 ...

  5. drf02 序列化器详解 Serializer

    作用 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型3. 反 ...

  6. 16-DRF工程搭建与序列化器

    1.DRF工程搭建 环境安装与配置 DRF是以Django扩展应用的方式提供的,所以我们可以直接利用Django环境,而无需创建(先创建Django环境). 1.安装DRF pip3 install ...

  7. DRF序列化器的使用

    序列化器的使用 序列化器的使用分两个阶段: 在客户端请求时,使用序列化器可以完成对数据的反序列化. 在服务器响应时,使用序列化器可以完成对数据的序列化. 序列化的基本使用 使用的还是上一篇博文中使用的 ...

  8. Django-DRF组件学习-环境安装与配置与序列化器学习

    1.DRF环境安装与配置 DRF需要以下依赖: Python (2.7, 3.2, 3.3, 3.4, 3.5, 3.6) Django (1.10, 1.11, 2.0) DRF是以Django扩展 ...

  9. Cf序列化器-Serializer解析

    Cf序列化器-Serializer 定义序列化器 Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Seri ...

随机推荐

  1. 对ThreadLocal的理解

      参考文档:https://www.cnblogs.com/moonandstar08/p/4912673.html   一.定义:线程本地变量,每个线程中的变量相互独立,互不影响. 官方定义: 1 ...

  2. Navicat Premium教程

    介绍 Navicat premium是一款数据库管理工具,是一个可多重连线资料库的管理工具,它可以让你以单一程式同时连线到 MySQL.SQLite.Oracle 及 PostgreSQL 资料库,让 ...

  3. RocketMQ控制台命令

    本文未完成,有空再补充,不小心发布了,抱歉 Rocket版本:4.3.0 这几天在整RocketMQ,可谓是困难重重,其中关于控制台的命令,网上的都是一半一半的, 所以我打算直接用整一个完整的官方的命 ...

  4. android基础---->Parcelable的使用

     android中Parcelable序列化的使用,简单的记录一下. 目录导航: Serializable在android中的使用 Parcelable在android中的使用 Serializabl ...

  5. Spark直接读入fastq格式的数据

    输入文件: fastq格式 输出结果: kmer的频数和对应的kmer类型 系统环境Ubuntu单机版17.01 spark版本2.7 此次测试主要用到了RDD的函数foreach和zipWithIn ...

  6. 剑指offer25:复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),结果返回复制后复杂链表的head。

    1 题目描述 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head.(注意,输出结果中请不要返回参数中的节点引用 ...

  7. 用selenium控制已打开的浏览器

    在使用selenium进行自动化测试会遇到,手工打开浏览器,做了一部分操作后,并打开相关页面后再执行相关的自动化脚本. 如何使用selenium来接管先前已打开的浏览器呢?醍提出一个Google Ch ...

  8. 第四章 函数之lambda 表达式和内置函数

    4.5 lambda 表达式 用于表示简单的函数. # 三元运算,为了解决简单的if else的情况,如:if 1 == 1:    a = 123else:    a = 456# 相当于a = 1 ...

  9. PAT(B) 1083 是否存在相等的差(Java)统计

    题目链接:1083 是否存在相等的差 (20 point(s)) 题目描述 给定 N 张卡片,正面分别写上 1.2.--.N,然后全部翻面,洗牌,在背面分别写上 1.2.--.N.将每张牌的正反两面数 ...

  10. mongodb 启动及创建用户

    1. 守护进程启动,参考: https://blog.csdn.net/jj546630576/article/details/81117765 2. 用户管理参考: https://www.cnbl ...