聊聊RedisTemplate的各种序列化器

news2024/11/26 4:27:08

[版权申明] 非商业目的注明出处可自由转载
出自:shusheng007

文章目录

  • 概述
  • 序列化器
    • 作用和原理
    • JDK 序列化方式
      • 多一点
    • String 序列化方式
    • JSON 序列化方式
  • 总结
  • 源码

概述

在SpringBoot中使用redis基本上都是通过Spring Data Redis,那就不得不说RedisTemplate了。在我刚接触它的时候比较懵逼的就是给其设置各种序列化器了,今天我们来唠唠他们。

序列化器

众所周知,使用RedisTemplate可以对Redis的各种数据结构进行操作,如下图所示。

在这里插入图片描述

作用和原理

那我们为什么需要序列化器呢,这是个啥玩意儿?

现在闭目思考一下我们是如何使用redis的?是不是先将数据存储在redis上,然后用的时候再读取出来?

那我们存储在redis里的内容是啥呢?有时是字符串,例如"ShuSheng007",大部分时间是对象,例如StudentList<Student>Map<String,Student>等等。这些个对象肯定是不能直接存储到redis上的,我们需要想办法先把它们转成byte[]后才能存储到redis上,这就是所谓的序列化。等用的时候还的把byte[]转化为相应的对象,这就是所谓的反序列化。序列化器就是完成这两个功能的。

下面是Spring中Redis序列化器的接口,从源码中可以非常清晰的看到它就干了这两个事情。

public interface RedisSerializer<T> {

	@Nullable
	byte[] serialize(@Nullable T t) throws SerializationException;

	@Nullable
	T deserialize(@Nullable byte[] bytes) throws SerializationException;
}

之所以存在这么多序列化器,是因为我们可以通过各种方式将对象转为byte[],也就是这个接口可以有各种实现类。总结一下,大概有如下几种:

  • JDK 序列化方式 (默认)
  • String 序列化方式
  • JSON 序列化方式
  • XML 序列化方式

其中XML序列化器不怎么用,我们就忽略它吧。

在讲解各种序列化器之前我们应该先搞清楚RedisTemplate都有哪些地方需要设置序列化器。

public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {

	@SuppressWarnings("rawtypes") private @Nullable RedisSerializer keySerializer = null;
	@SuppressWarnings("rawtypes") private @Nullable RedisSerializer valueSerializer = null;
	@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashKeySerializer = null;
	@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashValueSerializer = null;
	
}

从上面的源码可以发现总共有四个地方需要设置序列化器。这个和Redis提供的数据结构有关,所以我们在往redis里面存放数据的时候有两种方式。一种是key/value形式,另一种就是 key/hashMap, 那个hashMap又是key/value形式, 所以一共有四个地方用到序列化器。

key和hashKey一般都使用String序列化方式,有变化的一般是value和hashValue。

JDK 序列化方式

JdkSerializationRedisSerializer完成,它是默认序列化器,如果不手动设置就会使用它。它是利用Java自身提供的序列化方案来工作的,也就是说你要存放到redis中的数据必须是可序列化的,例如实现了Serializable接口。

我们来实践一下,使用下面的代码就给RedisTemplate的value设置JdkSerializationRedisSerializer

template.setKeySerializer(RedisSerializer.string());
template.setValueSerializer(RedisSerializer.java());

我们有如下一个类

public class KeyValue implements Serializable {
    private String key;
    private Object value;
    ...
}

将其保存到redis中

public void testRedisSerializer() {
    ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
    valueOperations.set("object",new KeyValue("age",18));
}

查看结果,你会发现value是人类不可读的样子

\xac\xed\x00\x05sr\x00.top.shusheng007.redisintegrate.domain.KeyValue\xb2\xf9\xec\xa5\xb5\x89\xb99\x02\x00\x02L\x00\x03keyt\x00\x12Ljava/lang/String;L\x00\x05valuet\x00\x12Ljava/lang/Object;xpt\x00\x03agesr\x00\x11java.lang.Integer...

正是因为这个原因,外加跨平台问题导致其在生产中用的也比较少。

多一点

如果在创建JdkSerializationRedisSerializer时传入一个ClassLoader,如果这个类加载器和你使用类的加载器是同一个的话,查询出的值可以直接转成对应的类型对象的。

//传入当前配置类的ClassLoader
template.setValueSerializer(RedisSerializer.java(getClass().getClassLoader()));

valueOperations.set("object",new KeyValue("age",18));
//从redis获取的值可以直接强转
KeyValue keyValue = (KeyValue) valueOperations.get("object");

String 序列化方式

StringRedisSerializer完成,这个应该没什么可说的。一般情况下,key和hashKey都使用这个序列化器,它们两一般也就存放字符串。value和hashValue一般都不会设置为它,Spring Data Redis 单独提供了一个操作字符串的StringRedisTemplate

public class StringRedisTemplate extends RedisTemplate<String, String> {
	...
}

JSON 序列化方式

GenericJackson2JsonRedisSerializer或者Jackson2JsonRedisSerializer完成。我们一般将value和hashValue的序列化器设置为其中一个,用来以json的形式保存数据。那这两个有什么区别呢?

  • Jackson2JsonRedisSerializer

设置序列化器

Jackson2JsonRedisSerializer<Object> valuesSerializer2 = new Jackson2JsonRedisSerializer(Object.class);
template.setValueSerializer(valuesSerializer2);

使用

 valueOperations.set("object",new KeyValue("age",18));

 Object keyValue =  valueOperations.get("object");
 
 String clsName = keyValue.getClass().getCanonicalName();
 log.info("object:{},name:{}", keyValue,clsName);

查看redis中value值,可见就是普通json格式

{
	"key": "age",
	"value": 18
}

其中那个keyValue是一个java.util.LinkedHashMap类型,这个是java自动解析的类型。所以如果我们要将其解析成对应的类型的话就要借助与Jackson了。

 ObjectMapper objectMapper = new ObjectMapper();
 KeyValue keyValue = objectMapper.convertValue(keyValue, KeyValue.class);
  • GenericJackson2JsonRedisSerializer

这个与Jackson2JsonRedisSerializer的区别是生成的json里携带了类信息,反序列化为同一个类的时候不需要借助于Jackson。但这也会产生新的问题,例如一个服务向redis里写数据,另一个服务取数据,但是他们的类信息不一样就无法反序列化了。

设置序列化器

Jackson2JsonRedisSerializer<Object> valuesSerializer2 = new Jackson2JsonRedisSerializer(Object.class);
template.setValueSerializer(valueSerializer);

使用,注意我们在反序列化的时候直接进行了强转。

 valueOperations.set("object",new KeyValue("age",18));

 KeyValue keyValue = (KeyValue) valueOperations.get("object");

 String clsName = keyValue.getClass().getCanonicalName();
 log.info("object:{},name:{}", keyValue,clsName);

查看redis中value值,可见多了一个@class信息,是在反序列时提供类型信息的。

{
	"@class": "top.shusheng007.redisintegrate.domain.KeyValue",
	"key": "age",
	"value": 18
}

总结

通常key/hashKey使用字符串序列化器,value/hashValue使用Json序列化器。当服务自己存自己取的话使用GenericJackson2JsonRedisSerializer,但是如果取其他服务存储的Json值就要使用Jackson2JsonRedisSerializer

以上就是RedisRemplate的几个序列化器的总结。是不是感觉也没那么难了?小白面前的大山就是老鸟眼中的土坷垃。你回头看看你的经历,是不是很多当时感觉非常艰难的事情在你攻克他们后感觉也没那么难,而且还会感慨一句:这也没多难,为什么我当时就是不会呢?人生也是一样,当你回顾你的一生时大多遗憾的事情都是没有做的事情…

源码

一如既往,你可以从首发找到源码 redis-integration

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/878027.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据--难点--地图的制作

地图一直是亮点也是难点&#xff0c;刚刚进公司的时候也很难懂~~做出来的也很难看 纯CSS3使用vw和vh视口单位实现h5页面自适应&#xff0c;gulp自动监听sass改动并保存到css中 当修改了sass里面的代码后&#xff0c;gulp会自动监听修改内容并同名保存到css文件夹中&#xff0…

MySQL8.xx一主两从复制安装与配置

搭建环境: 查看系统版本cat /etc/redhat-release [rootwww tools]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) 查看内核版本cat /proc/version 目标: 一主两从 主机IP 主机名称 端口 搭建环境 安装目录192.168.1.100 docker…

祝金榜题名!64页Python基础学习手册!背完小白变大牛!

Python是一个温柔而强大的编程语言~在学习之初整个人都是小兴奋&#xff0c;学习中途遇到了各种问题但是我们坚持着。从一些基础概念的学习&#xff0c;到变量、函数、模块、流程控制、循环语句等等&#xff0c;Python的基础内容真心丰富呢~ 今天&#xff0c;给大家share一份我…

0142 存储系统2

目录 3.存储系统 3.4外部存储器 3.5高速缓冲存储器 3.6虚拟存储器 部分习题 3.存储系统 3.4外部存储器 3.5高速缓冲存储器 3.6虚拟存储器 部分习题 1.一个磁盘转速为7200转/分&#xff0c;每个磁道有160个扇区&#xff0c;每个扇区有512字节&#xff0c;则在理想情况下&…

九、多态(2)

本章概要 构造器和多态 构造器调用顺序继承和清理构造器内部多态方法的行为 协变返回类型使用继承设计 替代 vs 扩展向下转型与运行时类型信息 构造器和多态 通常&#xff0c;构造器不同于其他类型的方法。在涉及多态时也是如此。尽管构造器不具有多态性&#xff08;事实上…

JavaFx基础学习【三】:Scene

一、介绍 Scene&#xff0c;就是场景&#xff0c;在整体结构中&#xff0c;就是蓝色那一块的 为了更好的体验出什么是Scene&#xff0c;以下提供了两个不同背景颜色的Scene&#xff0c;让大家知道是在Application中是处于哪一块&#xff0c;从图中我们可以很容易看出来&#x…

CityGML程序化建模开源引擎及数据集

在攻读博士学位期间&#xff0c;我在 3D GIS 研究中遇到了以下缺点&#xff1a; 包含多个细节级别的 CityGML 数据集很少。不存在程序化生成的 CityGML 格式的数据。没有免费的程序化建模引擎。公开可用的 CityGML 模型通常包含大量&#xff08;拓扑&#xff09;错误。 推荐&a…

ME3116电源小板

最近设计一款PCB的时候使用微盟的dc dc电源ic踩了一个坑。 在使用me3116作为24v到5v的降压ic作为esp32系统前级的降压电路时&#xff0c;再没有铂电阻采样负载的情景下工作正常&#xff0c;带上负载后&#xff0c;ic工作不正常&#xff0c;过一段时间&#xff0c;后级电路会烧…

BBR拥塞控制算法 v3

BBR (Bottleneck Bandwidth and Round-trip propagation time) 是谷歌在 2016 年发布的一套拥塞控制算法。它尤其适合在存在一定丢包率的弱网环境下使用。比如谷歌就通过 BBR 让内部和外部的网络能够以更高吞吐量和更低延迟更高效地运行。在这类环境下&#xff0c;BBR 的性能远…

visual studio 2017 运行的程序关闭后不能再运行?(visual studio建立项目之后退出,如何再次完整打开项目?)

在你储存项目的文件夹里面应该是这样的 里面.vcxproj后缀名的就是原来创建的项目&#xff0c;直接打开这个头文件源文件就会一起出来了&#xff01; 真的管用&#xff0c;亲测有效。

el-calendar的样式修改使用记录

效果图与element原图 el-calendar的尺寸 el-calendar的大小是根据内部每一个日历块进行决定的 .el-calendar-day {height: 47px !important;border: none;text-align: center;padding: 0;} 右上角的上月下月&#xff0c;取消显示今天的css // 今天按钮隐藏.el-button-group …

2009年下半年 软件设计师 上午试卷

博主介绍&#xff1a;✌全网粉丝3W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

新增守护进程管理、支持添加MySQL远程数据库,支持PHP版本切换,1Panel开源面板v1.5.0发布

2023年8月14日&#xff0c;现代化、开源的Linux服务器运维管理面板1Panel正式发布v1.5.0版本。 在这个版本中&#xff0c;1Panel新增了守护进程管理功能&#xff1b;支持添加MySQL远程数据库&#xff1b;支持添加FTP/S和WebDAV的SFTP服务&#xff1b;支持PHP版本切换。此外&am…

从零开始,快速打造租车服务小程序的分享

随着移动互联网的发展&#xff0c;小程序成为了企业推广和服务的重要手段之一。租车服务行业也不例外&#xff0c;通过打造一款租车服务小程序&#xff0c;企业可以更好地与用户进行互动和交流&#xff0c;提供更方便快捷的租车服务。本文将介绍如何利用第三方制作平台/工具快速…

ORB-SLAM2学习笔记7之System主类和多线程

文章目录 0 引言1 整体框架1.1 整体流程 2 System主类2.1 成员函数2.2 成员变量 3 多线程3.1 ORB-SLAM2中的多线程3.2 加锁 0 引言 ORB-SLAM2是一种基于特征的视觉SLAM&#xff08;Simultaneous Localization and Mapping&#xff09;系统&#xff0c;它能够从单个、双目或RBG…

理解jvm之对象已死怎么判断?

目录 引用计数算法 什么是引用 可达性分析算法&#xff08;用的最多的&#xff09; 引用计数算法 定义&#xff1a;在对象中添加一个引用计数器&#xff0c;每当有一个地方引用它时&#xff0c;计数器值就加一&#xff1b;当引用失效时&#xff0c;计数器值就减一&#xff1…

用ngrok实现内网穿透,一行命令就搞定!

最近在写支付的东西&#xff0c;调试时候需要让支付平台能够回调本地接口来更新支付成功的状态。但由于开发机器没有公网IP&#xff0c;所以需要使用内网穿透来让支付平台能够成功访问到本地开发机器&#xff0c;这样才能更高效率的进行调试。 推荐内网穿透的文章已经很多很多…

Stable Diffusion 插件开发经验

Stable Diffusion近来大热,但是插件开发的资料少之又少。 这里提供一些插件开发的经验,可供参考。 1.替换启动页。 如果你想要在运行Stable Diffusion的基础上想要一些独有的操作,不想要进行裁剪,直接替换启动页面,那么就需要在webui中进行替换 这里modules.ui.create_ui…

FPGA通过MIG IP读写DDR3

一. 简介 本期将接收如何驱动DDR3存储器&#xff0c;当然不会像SDRAM那样&#xff0c;自己手写驱动&#xff1b;而是借助Vivado提供的MIG IP来完成这项工作。但是建议在学习DDR3之前&#xff0c;可以学习一下且写一下SDRAM的驱动&#xff0c;因为它们的涉及到的存储原理和框架…

THUDM/chatglm2-6b-int4体验

在gpu下 gpu&#xff1a; Telsa T4 资源消耗&#xff1a;RAM大概4G&#xff0c;GPU显存大概6G # 安装transformers等包 !pip install protobuf transformers4.30.2 cpm_kernels torch>2.0 gradio mdtex2html sentencepiece accelerate# 导入AutoTokenizer, AutoModel from…