聊聊RedisTemplate的各种序列化器

[版权申明] 非商业目的注明出处可自由转载
出自: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> {@Nullablebyte[] serialize(@Nullable T t) throws SerializationException;@NullableT 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.rhkb.cn/news/90011.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手机照片误删怎么办,电脑照片误删怎么办怎么才能找回,EasyRecovery来帮您

手机照片误删怎么办&#xff0c;电脑照片误删怎么办怎么才能找回&#xff0c;EasyRecovery 2023来帮您&#xff01;&#xff01;&#xff01; EasyRecovery 2023是一款操作安全、价格便宜、用户自主操作的 数据恢复 方案&#xff0c;它支持从各种各样的 存储介质 恢复删除 或者…

Nginx安装及Minio集群反向动态代理配置(二)

安装所需插件 1、安装gcc gcc是linux下的编译器在此不多做解释&#xff0c;感兴趣的小伙伴可以去查一下相关资料&#xff0c;它可以编译 C,C,Ada,Object C和Java等语言 命令&#xff1a;查看gcc版本 [rootwww ~]# gcc -v -bash: gcc: 未找到命令 说明没有安装: 那就直接yu…

机器人CPP编程基础-02变量Variables

机器人CPP编程基础-01第一个程序Hello World 基础代码都可以借助人工智能工具进行学习。 C #include<iostream>using namespace std;main() {//Declaring an integer type variable A, allocates 4 bytes of memory.int A4;cout<<A <<endl;//Prints the a…

即将发布的 Kibana 版本可运行 Node.js 18

作者&#xff1a;Thomas Watson Kibana 构建在 Node.js 框架之上。 为了确保每个 Kibana 版本的稳定性和使用寿命&#xff0c;我们始终将捆绑的 Node.js 二进制文件保持为最新的最新长期支持 (LTS) 版本。 当 Node.js 版本 18 升级到 LTS 时&#xff0c;我们开始将 Kibana 升级…

最新AI系统ChatGPT网站程序源码+搭建教程/公众号/H5端/安装配置教程/完整知识库

1、前言 SparkAi系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。 那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&#xff01;…

Linux文件属性查看和修改学习

一、基本属性 1、看懂文件属性&#xff1a; Linux系统是一种典型的多用户系统&#xff0c;不同的用户处于不同的地位&#xff0c;拥有不同的权限。为了保护系统的安全性&#xff0c; Linux系统对不同的用户访问同一文件&#xff08;包括目录文件&#xff09;的权限做了不同的…

工程监测振弦采集仪采集到的数据如何进行分析和处理

工程监测振弦采集仪采集到的数据如何进行分析和处理 振弦采集仪是一个用于测量和记录物体振动的设备。它通过测量物体表面的振动来提取振动信号数据&#xff0c;然后将其转换为数字信号&#xff0c;以便进行分析和处理。在实际应用中&#xff0c;振弦采集仪是广泛应用于机械、建…

力扣刷题(C++)知识点

一&#xff0c;找到数组的中间位置 这个是错的&#xff0c;不能分开来 C vector<int>& nums 用法 创建一维数组vector&#xff1a; vector<int> nums; //不指定长度vector<int> nums(n); //指定长度为n c &#xff1c;numeric&#xff1e; accumul…

解决方案 | 法大大加速医疗器械行业创新升级

科技的不断进步&#xff0c;带动医疗器械产品不断创新升级。数字化、智能化的技术也开始广泛应用在医疗器械行业中。行业的蓬勃发展&#xff0c;进一步驱动了医疗器械行业规范化管理政策的出台&#xff0c;2019年&#xff0c;《医疗器械产品注册管理办法》&#xff08;2019&…

Linux 当fork在for循环中的问题

以下代码会打印几个"A"&#xff1f; 例1.代码如下&#xff1a; int main(int argc, char* argv[],char* envp[]) { for(int i 0;i < 2; i ) { fork(); printf("A\n"); } exit(0); } 代码分析&#xff1a; //父进程for(int i …

【C语言】const修饰普通变量和指针

大家好&#xff0c;我是苏貝&#xff0c;本篇博客是系列博客每日一题的第一篇&#xff0c;本系列的题都不会太难&#xff0c;如果大家对这种系列的博客感兴趣的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 文章目录 一.const修饰普通变量二.const修饰指…

echarts绘制仪表盘

代码展示&#xff1a; /**绘制仪表盘图表 */function drawInstrument(id) {setTimeout(()> {var chart echarts.init(document.getElementById(id)); var option {series: [{name: 风险指数,type: gauge,center: [50%, 60%],radius: 90%,min: chartData.min,max: chartDat…

Opencv将数据保存到xml、yaml / 从xml、yaml读取数据

Opencv将数据保存到xml、yaml / 从xml、yaml读取数据 Opencv提供了读写xml、yaml的类实现&#xff1a; 本文重点参考&#xff1a;https://blog.csdn.net/cd_yourheart/article/details/122705776?spm1001.2014.3001.5506&#xff0c;并将给出文件读写的具体使用实例。 1. 官…

大模型相关知识

一. embedding 简单来说&#xff0c;embedding就是用一个低维的向量表示一个物体&#xff0c;可以是一个词&#xff0c;或是一个商品&#xff0c;或是一个电影等等。这个embedding向量的性质是能使距离相近的向量对应的物体有相近的含义&#xff0c;比如 Embedding(复仇者联盟)…

【JavaWeb】实训的长篇笔记(下)

文章目录 八、功能实现1、注册功能2、登录功能3、问题说明4、首页数据显示5、后台管理 八、功能实现 1、注册功能 jsp&#xff1a;能够在页面中把数据动态化&#xff0c;jsp和html在元素标签上是无区别的&#xff0c;区别是html中写上java代码就成了jsp文件。filename.jsp。 需…

Go http.Handle和http.HandleFunc的路由问题

Golang的net/http包提供了原生的http服务&#xff0c;其中http.Handle和http.HandleFunc是两个重要的路由函数。 1. 函数介绍 http.HandleFunc和http.Handle的函数原型如下&#xff0c;其中DefaultServeMux是http包提供的一个默认的路由选择器。 func HandleFunc(pattern st…

关于MYSQL日期相减问题

错误写法&#xff1a; SELECT DATE_FORMAT(STR_TO_DATE(20230701,%Y%m%d) -60,%Y%m%d); 但是这种格式有个问题&#xff0c;则会输出空。 正确写法&#xff1a; SELECT DATE_FORMAT(DATE_SUB(20230701,INTERVAL 60 DAY),%Y%m%d);

基于Spring Boot的高校图书馆管理系统的设计与实现(Java+spring boot+MySQL)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于Spring Boot的高校图书馆管理系统的设计与实现&#xff08;Javaspring bootMySQL&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1a;Java sp…

C++QT教程3——手册4.11.1自带教程(笔记)——创建一个QT快速应用

文章目录 创建一个QT快速应用创建项目创建主视图添加应用逻辑为视图添加动画素材文件 参考文章 创建一个QT快速应用 本教程使用内置的QML类型&#xff0c;介绍了Qt Quick的基本概念。有关可以选择的用户界面选项的更多信息&#xff0c;请参阅用户界面。 本教程描述了如何使用…

实现C++多线程的完全指南

目录 引言&#xff1a;1. 理解多线程编程的基本概念2. 引入C标准库中的线程库3. 创建线程4. 线程同步和互斥5. 线程间的通信使用多线程需要关注的要点结论&#xff1a; 引言&#xff1a; 在现代软件开发中&#xff0c;多线程编程已经成为一项非常重要的技能。通过利用多线程&a…