自定义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.rhkb.cn/news/331145.html

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

相关文章

Leetcode刷题笔记2

283. 移动零 283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 数据划分、数据分块 利用数组下标充当指针cur&#xff1a;从左往右扫描数组&#xff0c;遍历数组dest&#xff1a;已处理的区间内&#xff0c;非零元素的最后一个位置 一共被分为三个区间 [0,dest] [dest1,cu…

42-3 应急响应之服务排查

一、服务排查 服务是后台运行的进程,可在计算机启动时自动启动,也可暂停和重新启动,且不显示用户界面。它们特别适用于长时间运行的功能,以避免影响其他用户在同一台计算机上的工作。在应急响应中,服务常被恶意软件用作驻留方法。 二、Windows服务排查 打开【运行】对话框…

【C++项目】实时聊天的在线匹配五子棋对战游戏

目录 项目介绍 开发环境 核心技术 项目前置知识点介绍 Websocketpp 1. WebSocket基本认识 2. WebSocket协议切换原理解析 3. WebSocket报文格式 4. Websocketpp介绍 5. 搭建一个简单WebSocket服务器 JsonCpp 1. Json格式的基本认识 2. JsonCpp介绍 3. 序列化与反序…

iPhone实况照片从Windows资源管理器复制的JPG+MOV无法正常还原到iPhone

背景&#xff1a; 之前使用的iPhone 15 Pro&#xff0c;使用的Windows资源管理器当中复制导出的实况照片&#xff0c;复制出来的格式例如IMG_0001.JPG, IMG_0001.MOV。之后手机就卖掉了。现在使用的iPhone 14 Pro Max&#xff0c;想要导回之前备份的实况照片。尝试使用爱思助手…

VBA即用型代码手册:删除Excel中空白行Delete Blank Rows in Excel

我给VBA下的定义&#xff1a;VBA是个人小型自动化处理的有效工具。可以大大提高自己的劳动效率&#xff0c;而且可以提高数据的准确性。我这里专注VBA,将我多年的经验汇集在VBA系列九套教程中。 作为我的学员要利用我的积木编程思想&#xff0c;积木编程最重要的是积木如何搭建…

一篇文章讲透排序算法之希尔排序

希尔排序是对插入排序的优化&#xff0c;如果你不了解插入排序的话&#xff0c;可以先阅读这篇文章&#xff1a;插入排序 目录 1.插入排序的问题 2.希尔排序的思路 3.希尔排序的实现 4.希尔排序的优化 5.希尔排序的时间复杂度 1.插入排序的问题 如果用插入排序对一个逆序…

单片机设计注意事项

1.电源线可以30mil走线&#xff0c;信号线可以6mil走线 2.LDO推荐 SGM2019-3.3,RT9013,RT9193,1117-3.3V。 3.单片机VCC要充分滤波后再供电&#xff0c;可以接0.1uf的电容 4.晶振附件不要走其他元件&#xff0c;且放置完单片机后就放置晶振&#xff0c;晶振靠近X1,X2。

SpringBoot高级原理详解

文章目录 1 SpringBoot自动化配置原理01-SpringBoot2高级-starter依赖管理机制02-SpringBoot2高级-自动化配置初体验03-SpringBoot2高级-底层原理-Configuration配置注解04-SpringBoot2高级-底层原理-Import注解使用105-SpringBoot2高级-底层原理-Import注解使用206-SpringBoot…

微信小程序上线必备:SSL证书申请以及安装

一、认识ssl证书 1、ssl证书是什么&#xff1f; SSL证书&#xff0c;全称Secure Socket Layer Certificate&#xff0c;是一种数字证书&#xff0c;它遵循SSL&#xff08;现在通常指TLS&#xff0c;Transport Layer Security&#xff09;协议标准&#xff0c;用于在客户端&…

打造AI虚拟伴侣 - 优化方案

第一部分:框架优化概述 1、精确定位: 构建一个高度灵活且用户友好的平台,旨在通过无缝集成多种大型语言模型(LLMs)后端,为用户创造沉浸式的角色交互体验。不仅适配电脑端,还特别优化移动端体验,满足二次元AI虚拟伴侣市场的特定需求。 2、核心功能强化: 增强后端兼容…

k8s——Pod详解

一、Pod基础概念 1.1 Pod定义 Pod是kubernetes中最小的资源管理组件&#xff0c;Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是围绕着Pod来进行支撑和扩展Pod功能的&#xff0c;例如&#xff0c;用于管理Pod运行…

华为云服务培训

一、存储类服务实践 是什么&#xff1a; 云硬盘( Elastic Volume Service )是一种为 ECS&#xff08;弹性云服务器&#xff09;、BMS&#xff08;裸金属服务器&#xff09; 等计算服务提供持久性存储的服务。 作用&#xff1a; 它通过数据冗余和缓存加速等多项技术&#xf…

【C++高阶(一)】继承

目录 一、继承的概念 1.继承的基本概念 2.继承的定义和语法 3.继承基类成员访问方式的变化 ​编辑 4.总结 二、基类和派生类对象赋值转换 三、继承中的作用域 四、派生类的默认成员函数 1.派生类中的默认构造函数 2.派生类中的拷贝构造函数 3.派生类中的移动构造函数…

[国产大模型简单使用介绍] 开源与免费API

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 随着大模型技术蓬勃发展和开源社区越来越活跃,国内的大模型也如雨后春笋一般.这时,一些就会问了,有了llama3,Mistral还有Gemma等等,国外大厂接连发力,一些开源社区也会有一些不错的模型,国内怎么比?对一个人使用,oll…

02.爬虫---HTTP基本原理

02.HTTP基本原理 1.URI 和 URL 的区别2.HTTP 和 HTTPS 的区别3.请求过程 1.URI 和 URL 的区别 URL&#xff08;Uniform Resource Locator&#xff09;即-统一资源定位符 URL是用来定位和访问互联网上资源的独特标识&#xff0c;它包括了资源的位置&#xff08;如IP地址或域名&a…

node.js —— 解读http模块

目录 http模块&#xff1a; http模块的引入&#xff1a; 创建web服务器的基本步骤&#xff1a; web服务器的一些基本属性&#xff1a; 上述知识汇总案例&#xff1a; http模块&#xff1a; http模块的引入&#xff1a; const http require (http) 创建web服务器的基本步骤…

记录docker ps查找指定容器的几个命令

1.docker ps | grep registry 查询包含registry的容器 2.docker ps | grep -E "reigistry\s" 开启正则匹配模式&#xff0c;匹配registry后面为空格的容器&#xff0c;若是匹配一整行可以这样写docker ps | grep -E "^([0-9a-f]{12})\sregistry\s.*" 这…

第八节 条件装配案例讲解

一、条件装配的作用是什么 条件装配是 Spring 框架中一个强大的特性&#xff0c;使得开发者能够创建更加灵活和可维护的应用程序。在 Spring Boot 中&#xff0c;这个特性被大量用于自动配置&#xff0c;极大地简化了基于 Spring 的应用开发。 二、条件装配注解 <dependen…

Android-自定义三角形评分控件

效果图 序言 在移动应用开发中&#xff0c;显示数据的方式多种多样&#xff0c;直观的图形展示常常能带给用户更好的体验。本文将介绍如何使用Flutter创建一个自定义三角形纬度评分控件&#xff0c;该控件可以通过动画展示评分的变化&#xff0c;让应用界面更加生动。 实现思…

Vue3实战easypan(六):回收站+设置

一、回收站 src/views/recycle/Recycle.vue <template><!-- 上方两个按钮 --><div class"top"><el-button type"success" :disabled"selectFileIdList.length 0" click"revertBatch"><span class"ic…