自定义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、多号同时登录在线 系统支持多个微信号同…

【记录一个问题】username@hostname:~$ 变为 -bash-4.2$

当命令行提示符从常规的 $ 或 usernamehostname:~$ 变为 -bash-4.2$&#xff0c;这通常表明你的shell会话丢失了对当前用户环境的一些关键信息&#xff0c;特别是关于用户主目录&#xff08;通常是 /home/username&#xff09;的信息。 原因 用户主目录丢失&#xff1a; 最可…

【综合类型第 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总线广泛应用于连接显卡&#…

JacksonConfig 配置 Long 序列化规则

JacksonConfig 配置 Long 序列化规则 将超长 long 值转换为 string&#xff0c;解决前端 JavaScript 最大安全整数是 2^53-1 的问题&#xff1b; 自定义Long序列化规则 import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerP…

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

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

mysql-差异备份详细流程

4.差异备份流程 差异备份流程&#xff08;重要) 第一次完整备份 innobackupex /xtrabackup innobackupex --userroot --password123456 /xtrabackup2024-05-23_20-25-05 第一次完整备份 2024-05-23_20-40-55 第二次差异备份 2024-05-23_20-47-37 第三次差异备份再往数据库里面…

特殊变量笔记2

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

软件工程基础知识

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

使用 sync_sso 同步 DiscourseConnect 用户数据 [Java]

最近有一个使用 SSO 把已有的用户同步到 Discourse 的需求。 所以&#xff0c;我就根据官方针对 PHP 实现&#xff08;Sync DiscourseConnect user data with the sync_sso route - developers - Discourse Meta &#xff09;写了一个有关 Java 的实现。 实现的方法很简单&am…

07网络编程及网络基础知识

【一】C/S模型和B/S模型 1.C/S模型----》c是指客户端&#xff0c;请求服务的&#xff0c;s是服务端&#xff0c;提供服务的 2.B/S模型----》B/S架构本质也是C/S架构让浏览器充当各个厂家的客户端 用户无需对应下载相应客户端 两种架构的优缺点C/S架构:王者荣耀优势:针对客户端…

using 用于枚举值

1. 用using声明枚举值 假设有一个限定范围的枚举类型(用枚举类声明): enum class Status{open, progress, done 9}; 与未限定作用域的枚举类型(不带类的枚举) 不同&#xff0c;此类型的值需要带有类型名的限定符: auto x Status::open; // OK auto x open; // ERROR…

腾讯云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;能…