自定义RedisTemplate序列化器

大纲

  • RedisSerializer
  • FastJsonRedisSerializer
  • 自定义二进制序列化器
  • 总结
  • 代码

在《RedisTemplate保存二进制数据的方法》一文中,我们将Java对象通过《使用java.io库序列化Java对象》中介绍的方法转换为二进制数组,然后保存到Redis中。实际可以通过定制RedisTemplate序列化器来避开手工序列化和反序列化的工作。本文我们将介绍3种常见的序列化器。

RedisSerializer

package org.example.redistemplateexample.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;@Configuration
public class RedisTemplateBeansConfig {@Bean(name = "nomaljsonRedisTemplate")public <T> RedisTemplate<String, T> nomaljsonRedisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, T> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(connectionFactory);redisTemplate.setValueSerializer(RedisSerializer.json());redisTemplate.setHashValueSerializer(RedisSerializer.json());redisTemplate.setKeySerializer(RedisSerializer.string());redisTemplate.setHashKeySerializer(RedisSerializer.string());redisTemplate.afterPropertiesSet();return redisTemplate;}
}

主要设置ValueSerializer和HashValueSerializer。RedisSerializer.json()会将模板类型T的对象序列化为Json,然后保存到Redis中。
然后定义一个操作类,并使用上面创建的名字为nomaljsonRedisTemplate的redisTemplate。

package org.example.redistemplateexample.redis;import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import jakarta.annotation.Resource;@Component
public class NomalJsonOperation<T> {@Resource(name = "nomaljsonRedisTemplate")public RedisTemplate<String, T> redisTemplate;public void Set(String key, T value) {redisTemplate.opsForValue().set(key, value);}public T Get(String key) {return redisTemplate.opsForValue().get(key);}
}

测试代码如下

package org.example.redistemplateexample.redis;import org.example.redistemplateexample.pojo.BaseTypes;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class NomalJsonOperationTest {@Autowiredprivate NomalJsonOperation<BaseTypes> nomalJsonOperation;@Testpublic void testSetGet() {String key = "NomalJsonOperationTest";BaseTypes value = generate(2);nomalJsonOperation.Set(key, value);BaseTypes result = nomalJsonOperation.Get(key);assertEquals(value, result);}private BaseTypes generate(int mark) {BaseTypes baseTypes = new BaseTypes();baseTypes.setByteValue((byte) mark);baseTypes.setShortValue((short) mark);baseTypes.setIntValue(mark);baseTypes.setLongValue((long) mark);baseTypes.setFloatValue((float) mark);baseTypes.setDoubleValue((double) mark);baseTypes.setCharValue((char) mark);baseTypes.setBooleanValue(mark % 2 == 0);return baseTypes;}
}

在这里插入图片描述

FastJsonRedisSerializer

fastjson是阿里巴巴公司推出的json序列化库,在现实生产中广泛应用。
但是在我们的场景下,使用fastjson需要做一些特殊处理,模式也和其他两者不一样。

package org.example.redistemplateexample.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;@Configuration
public class RedisTemplateBeansConfig {@Bean(name = "fastjsonRedisTemplate")public RedisTemplate<String, Object> fastjsonRedisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(connectionFactory);redisTemplate.setValueSerializer(new FastJsonRedisSerializer(Object.class));redisTemplate.setHashValueSerializer(new FastJsonRedisSerializer(Object.class));redisTemplate.setKeySerializer(RedisSerializer.string());redisTemplate.setHashKeySerializer(RedisSerializer.string());redisTemplate.afterPropertiesSet();return redisTemplate;}
}

可以看到,我们需要使用RedisTemplate<String, Object>,即模板类的第二类名需要使用Object。这是因为FastJsonRedisSerializer的构造需要指定Class<T>,而我们又不能通过函数的返回值类型T推导出Class<T>,所以只能使用Object.class这种通用的类型。当然,如果不需要使用模板类型,即让RedisTemplate只支持某个特定类型的Value,则可以直接指定确定的类型,而不用使用Object。
相对应的操作类,Get方法也只能返回Object,而不是模板类型T。

package org.example.redistemplateexample.redis;import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import jakarta.annotation.Resource;@Component
public class FastJsonOperation<T>  {@Resource(name = "fastjsonRedisTemplate")public RedisTemplate<String, T> redisTemplate;public void Set(String key, T value) {redisTemplate.opsForValue().set(key, value);}public Object Get(String key) {return redisTemplate.opsForValue().get(key);}
}

测试的代码如下

package org.example.redistemplateexample.redis;import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.example.redistemplateexample.pojo.BaseTypes;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class FastJsonOperationTest {@Autowiredprivate FastJsonOperation<BaseTypes> fastJsonOperation;@Testpublic void testSetGet() {String key = "FastJsonOperationTest";BaseTypes value = generate(2);fastJsonOperation.Set(key, value);BaseTypes result = JSONObject.parseObject(JSON.toJSONString(fastJsonOperation.Get(key)), BaseTypes.class);assertEquals(value, result);}private BaseTypes generate(int mark) {BaseTypes baseTypes = new BaseTypes();baseTypes.setByteValue((byte) mark);baseTypes.setShortValue((short) mark);baseTypes.setIntValue(mark);baseTypes.setLongValue((long) mark);baseTypes.setFloatValue((float) mark);baseTypes.setDoubleValue((double) mark);baseTypes.setCharValue((char) mark);baseTypes.setBooleanValue(mark % 2 == 0);return baseTypes;}
}

我们需要使用JSON.toJSONString将Fastjson序列化后的object转换成Json字符串,然后再使用JSONObject.parseObject将其转化成明确的类型BaseTypes。
这种转换让Fastjson方案黯然失色。
在这里插入图片描述

自定义二进制序列化器

最后我们介绍结合了《使用java.io库序列化Java对象》和《RedisTemplate保存二进制数据的方法》的方式。
首先定义序列化器IoSerializer,它继承于RedisSerializer。中间的序列化和反序列化步骤已经在《使用java.io库序列化Java对象》中有过介绍。

package org.example.redistemplateexample.config;import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;public class IoSerializer<T> implements RedisSerializer<T> {@Overridepublic byte[] serialize(T obj) throws SerializationException {if (obj == null) {return new byte[0];}ByteArrayOutputStream bos = new ByteArrayOutputStream();try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {oos.writeObject(obj);return bos.toByteArray();} catch (Exception e) {throw new SerializationException("Failed to serialize", e);}}@Overridepublic T deserialize(byte[] bytes) throws SerializationException {if (bytes == null || bytes.length == 0) {return null;}ByteArrayInputStream bis = new ByteArrayInputStream(bytes);try( ObjectInputStream ois = new ObjectInputStream(bis)) {T obj = (T) ois.readObject();return obj;} catch (Exception e) {throw new SerializationException("Failed to deserialize", e);}}
}

然后设置序列化器

package org.example.redistemplateexample.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;@Configuration
public class RedisTemplateBeansConfig {@Bean(name = "iomemoryRedisTemplate")public <T> RedisTemplate<String, T> iomemoryRedisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, T> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(connectionFactory);redisTemplate.setValueSerializer(new IoSerializer<T>());redisTemplate.setHashValueSerializer(new IoSerializer<T>());redisTemplate.setKeySerializer(RedisSerializer.string());redisTemplate.setHashKeySerializer(RedisSerializer.string());redisTemplate.afterPropertiesSet();return redisTemplate;}
}

再定义个操作类

package org.example.redistemplateexample.redis;import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import jakarta.annotation.Resource;@Component
public class IoMemoryOperation<T> {@Resource(name = "iomemoryRedisTemplate")public RedisTemplate<String, T> redisTemplate;public void Set(String key, T value) {redisTemplate.opsForValue().set(key, value);}public T Get(String key) {return redisTemplate.opsForValue().get(key);}
}

测试代码如下

package org.example.redistemplateexample.redis;import org.example.redistemplateexample.pojo.BaseTypes;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class IoMemoryOperationTest {@Autowiredprivate IoMemoryOperation<BaseTypes> ioMemoryOperation;@Testpublic void testSetGet() {String key = "IoMemoryOperationTest";BaseTypes value = generate(2);ioMemoryOperation.Set(key, value);BaseTypes result = ioMemoryOperation.Get(key);assertEquals(value, result);}private BaseTypes generate(int mark) {BaseTypes baseTypes = new BaseTypes();baseTypes.setByteValue((byte) mark);baseTypes.setShortValue((short) mark);baseTypes.setIntValue(mark);baseTypes.setLongValue((long) mark);baseTypes.setFloatValue((float) mark);baseTypes.setDoubleValue((double) mark);baseTypes.setCharValue((char) mark);baseTypes.setBooleanValue(mark % 2 == 0);return baseTypes;}
}

在这里插入图片描述

总结

  • 广泛使用的Fastjson在使用模板类时,类型转换比较丑陋。
  • iomemoryRedisTemplate和nomaljsonRedisTemplate被限制在Java工程中。特别是iomemoryRedisTemplate方案,因为它保存的是Java对象的二进制值。

代码

https://github.com/f304646673/RedisTemplateExample

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

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

相关文章

智能化让幼儿园管理更加规范

在各个学龄阶段&#xff0c;幼儿园一向都是家长的教师最为操心的&#xff0c;一方面幼儿园孩子自主才能差&#xff0c;安全问题需求分外注重&#xff0c;另一方面&#xff0c;幼儿园孩子年纪小、缺少必定的认知才能和区分才能&#xff0c;需求加强引导。 那么怎么进步幼儿园孩子…

D60SB120-ASEMI整流桥D60SB120参数、封装、尺寸

编辑&#xff1a;ll D60SB120-ASEMI整流桥D60SB120参数、封装、尺寸 型号&#xff1a;D60SB120 品牌&#xff1a;ASEMI 封装&#xff1a;D-SB 批号&#xff1a;2024 最大重复峰值反向电压&#xff1a;1200V 最大正向平均整流电流(Vdss)&#xff1a;60A 功率(Pd)&#x…

力扣--哈希表13.罗马数字转整数

首先我们可以知道&#xff0c;一个整数&#xff0c;最多由2个罗马数字组成。 思路分析 这个方法能够正确将罗马数字转换为阿拉伯数字的原因在于它遵循了罗马数字的规则&#xff0c;并且对这些规则进行了正确的编码和处理。 罗马数字规则 罗马数字由以下字符组成&#xff1a…

运维笔记.MySQL.基于mysqldump数据备份与恢复

运维专题 MySQL.基于mysqldump数据备份与恢复 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: [email protected]. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_2855…

多微信如何高效管理?一台电脑就能搞定!

对于有多个微信号的人来说&#xff0c;管理这些微信无疑是一道难题。 今天&#xff0c;就给大家分享一个能够让你高效管理多个微信号的神器——个微管理系统&#xff0c;下面&#xff0c;就一起来看看它都有哪些功能吧&#xff01; 1、多号同时登录在线 系统支持多个微信号同…

【综合类型第 39 篇】《我的创作纪念日》成为创作者的第2048天

这是【综合类型第 39 篇】&#xff0c;如果觉得有用的话&#xff0c;欢迎关注专栏。 前言 无意间看了一眼CSDN的私信&#xff0c;提示我 Allen Su &#xff0c;不知不觉今天已经是你成为创作者的 第2048天 啦&#xff0c;为了纪念这一天&#xff0c;我们为您准备了一份专属小…

2. PCI总线基本概念

PCI即Peripheral Componet Interconnect&#xff0c;中文意思是“外围器件互联”&#xff0c;是由PCISIG推出的一种局部并行总线标准。PCI总线是由ISA总线发展而来&#xff0c;是一种同步的独立于处理器的32位或64位局部总线。目前&#xff0c;PCI总线广泛应用于连接显卡&#…

操作抖音小店一直不出单怎么办?只需要做好这两点就可以了!

大家好&#xff0c;我是电商小V 最近很多新手小伙伴来咨询我说自己操作抖音小店&#xff0c;自己的店铺长时间不出单应该怎么办&#xff1f;今天咱们就来详细的说一下&#xff0c; 咱们要清楚的就是自己的店铺不出&#xff0c;只需要咱们做好这两点就可以了&#xff0c; 第一点…

特殊变量笔记2

案例需求 在demo4.sh中循环打印输出所有输入参数, 体验$*与$的区别 实现步骤 编辑demo4.sh脚本文件 # 增加命令: 实现直接输出所有输入后参数 # 增加命令: 使用循环打印输出所有输入参数演示 编辑demo4.sh文件 直接输出所有输入参数, 与循环方式输出所有输入参数(使用双引…

软件工程基础知识

一、软件工程概述 二、软件开发模型 三、软件开发方法 四、需求分析 五、系统设计 六、系统测试 七、软件开发项目管理 八、软件质量 九、软件度量

腾讯云COS上传文件出现的问题

1、没有配置 ObjectMetadata 的文件长度 腾讯云COS上传文件出现数据损坏问题_no content length specified for stream data. strea-CSDN博客 2、 使用 FileInputStream使用完没有及时关闭导致报错 ClientAbortException: java.nio.channels.ClosedChannelException 添加…

滑动谜题 leetcode的BFS题目 启发如何写一个拼图编程呢

题目链接 题目要求&#xff0c;要将上面的拼板拼成123450 首先&#xff0c;转换为字符串&#xff0c;为什么要转换为字符串呢&#xff0c;因为处理会变得很简单比如示例一&#xff0c;转化为字符串是12345&#xff0c;目标字符串为123450&#xff0c;只需要证明通过某种交换&a…

AI爆文写作:或许开放性的标题,才会更让人想点开了解答案

这是新华社公众号的一条推文 从信息传递上来说&#xff0c;新闻标题应该直接&#xff0c;包含关键信息。 但这个标题&#xff0c;却没有直接点名哪个国家&#xff0c;要点进去才能看到。 这就是要让人点开的标题特征&#xff0c;标题没有提供完整信息&#xff0c;是开放性的…

Apache Hive 安装与配置的详细教程

1. Hive简介 Hive是基于Hadoop的一个数据仓库工具&#xff0c;用来进行数据提取、转化、加载&#xff0c;这是一种可以存储、查询和分析存储在Hadoop中的大规模数据的机制。hive数据仓库工具能将结构化的数据文件映射为一张数据库表&#xff0c;并提供SQL查询功能&#xff0c;能…

infoq读书笔记-Davide Taibi博士-花8年转型微服务却得不到回报,问题出在哪 儿?

InfoQ&#xff1a;您的论文“On the Definition of Microservice Bad Smells”涉及非常多的微服务不良做法&#xff0c;但如果要用几个大类别来列举危害性比较大的微服务反模式&#xff0c;您认为会是哪几类&#xff1f;另外&#xff0c;您能再大概分析说明下造成这个几个反模式…

产品经理-产品设计规范(六)

1. 设计规范 2. 七大定律 2.1 菲茨定律 2.1.1 概念 2.1.2 理解 2.1.3 启示 按钮等可点击对象需要合理的大小尺寸根据用户使用习惯合理设计按钮的相对和绝对位置屏幕的边和角很适合放置像菜单栏和按钮这样的元素 2.1.4 参考使用手机习惯 2.1.5 案例 2.2 席克定律 2.2.1 概念 …

XShell-连接-Centos 7

XShell 连接Centos 7 一.准备 安装XShell XShell下载地址&#xff1a; 在虚拟机上安装Centos 7&#xff0c;具体操作自行学习 二.Centos 7的准备 1.网络适配器修改为NAT 2.获取IP 输入命令&#xff1a; ip addr我的Centos 7对外IP为192.168.174.129 三.XShell连接Cento…

【百度云千帆AppBuilder】诗词达人:AI引领的诗词文化之旅

文章目录 写在前面&#xff1a;百度云千帆AppBuilder诗词达人&#xff1a;AI引领的诗词文化之旅功能介绍&#xff1a;诗词达人智能体的深度体验1. 诗词接龙学习2. 诗词深度解析3. 互动式问答4. 诗词创作辅助 技术特点详解&#xff1a;"诗词达人"智能体的创新技术零代…

项目9-网页聊天室8(消息的发送和接收之websocket)

这是整个项目最最核心的部分. 但是这个部分的编写&#xff0c;需要依赖"基础设施" 包括不限于前面已经实现的 主界面,用户管理,会话管理, 好友管理, 消息管理 等等.... 发送消息,和接收消息,需要"实时传输 张三 发了一条消息,李四 这边立即就能接收到, 这样的…

【游戏引擎】Unity脚本基础 开启游戏开发之旅

持续更新。。。。。。。。。。。。。。。 【游戏引擎】Unity脚本基础 Unity脚本基础C#语言简介C#基础 Unity脚本基础创建和附加脚本MonoBehaviour生命周期生命周期方法 示例脚本 Unity特有的API常用Unity API 实践示例&#xff1a;制作一个简单的移动脚本步骤1&#xff1a;创建…