聊聊RedisTemplate的各种序列化器

news/2024/12/28 8:38:42/

[版权申明] 非商业目的注明出处可自由转载
出自: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.ppmy.cn/news/1033178.html

相关文章

数据可视化工具的三大类报表制作流程分享

电脑&#xff08;pc&#xff09;、移动、大屏三大类型的BI数据可视化报表制作步骤基本相同&#xff0c;差别就在于尺寸调整和具体的报表布局。这对于采用点击、拖拉拽方式来制作报表的奥威BI数据可视化工具来说就显得特别简单。接下来&#xff0c;我们就一起看看不这三大类型的…

Android AOSP源码编译——AOSP整编(二)

切换到源码目录下执行下面命令 1、初始化环境 . build/envsetup.sh //清除缓存 make clobber2、选择编译目标 lunchAOSP 预制了很多 Product。这里为了简单我们先不用真机&#xff0c;而是选择模拟器的方式&#xff0c;对于 x86_64 模拟器&#xff0c;我们选择的是 aosp_x86…

Dubbo 核心概念和架构

以上是 Dubbo 的工作原理图&#xff0c;从抽象架构上分为两层&#xff1a;服务治理抽象控制面 和 Dubbo 数据面 。 服务治理控制面。服务治理控制面不是特指如注册中心类的单个具体组件&#xff0c;而是对 Dubbo 治理体系的抽象表达。控制面包含协调服务发现的注册中心、流量管…

SQL-每日一题【1341. 电影评分】

题目 表&#xff1a;Movies 表&#xff1a;Users 请你编写一个解决方案&#xff1a; 查找评论电影数量最多的用户名。如果出现平局&#xff0c;返回字典序较小的用户名。查找在 February 2020 平均评分最高 的电影名称。如果出现平局&#xff0c;返回字典序较小的电影名称。 …

CTFshow 限时活动 红包挑战7、红包挑战8

CTFshow红包挑战7 写不出来一点&#xff0c;还是等了官方wp之后才复现。 直接给了源码 <?php highlight_file(__FILE__); error_reporting(2);extract($_GET); ini_set($name,$value);system("ls ".filter($_GET[1])."" );function filter($cmd){$cmd…

在矩池云使用 ChatGLM2-6B ptuning

本文参考 ChatGLM2-6B 官方文档&#xff0c;在矩池云复现了对于 ChatGLM2-6B 模型基于 P-Tuning v2 的微调。P-Tuning v2 将需要微调的参数量减少到原来的 0.1%&#xff0c;再通过模型量化、Gradient Checkpoint 等方法&#xff0c;最低只需要 7GB 显存即可运行。 官方文档地址…

《测试设计思想》——图书推荐

前言&#xff1a; 在当今软件行业飞速发展的时代&#xff0c;软件测试的重要性日益凸显。为了帮助读者提高测试效率和测试质量&#xff0c;清华大学出版社推出了一本名为《测试设计思想》的书籍&#xff0c;由知名专家周海旭老师撰写。这本书深入探讨了测试设计的思想和方法&am…

深入探讨代理技术:保障网络安全与高效爬虫

1. Socks5代理与IP代理的区别与应用 Socks5代理和IP代理是代理技术中的两个重要方面&#xff0c;它们有着不同的特点和应用场景。Socks5代理是一种协议&#xff0c;支持TCP和UDP流量传输&#xff0c;适用于需要实时数据传输的场景&#xff0c;例如在线游戏或实时通信应用。而I…