千家信息网

Redis中RedisTemplate怎么配置序列和反序列化

发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,这篇文章主要介绍"Redis中RedisTemplate怎么配置序列和反序列化",在日常操作中,相信很多人在Redis中RedisTemplate怎么配置序列和反序列化问题上存在疑惑,小编查阅了各式资
千家信息网最后更新 2025年01月19日Redis中RedisTemplate怎么配置序列和反序列化

这篇文章主要介绍"Redis中RedisTemplate怎么配置序列和反序列化",在日常操作中,相信很多人在Redis中RedisTemplate怎么配置序列和反序列化问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Redis中RedisTemplate怎么配置序列和反序列化"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

RedisTemplate配置 序列和反序列化

对于redis操作,springboot进行了很好的封装,那就是spring data redis。提供了一个高度封装的RedisTemplate类来进行一系列redis操作,连接池自动管理;同时将事务封装操作,交由容器进行处理。

针对数据的"序列化和反序列化",提供了多种策略(RedisSerializer)

默认为使用JdkSerializationRedisSerializer,同时还有StringRedisSerializer,JacksonJsonRedisSerializer,OxmSerializer,GenericFastJsonRedisSerializer。

简介一下

JdkSerializationRedisSerializer:POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。是目前默认的序列化策略。

StringRedisSerializer:Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是"new String(bytes, charset)"和"string.getBytes(charset)"的直接封装。是最轻量级和高效的策略。

JacksonJsonRedisSerializer:jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。【需要jackson-mapper-asl工具支持】

GenericFastJsonRedisSerializer:另一种javabean与json之间的转换,同时也需要指定Class类型。

OxmSerializer:提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的数据将是xml工具。不过使用此策略,编程将会有些难度,而且效率最低;不建议使用。【需要spring-oxm模块的支持】

实践

1)依赖(版本继承了SpringBoot版本)

   org.springframework.boot   spring-boot-starter-data-redis

2)RedisConfig类

添加bean,指定key/value以及HashKey和HashValue的序列化和反序列化为FastJson的。

package com.sleb.springcloud.common.config;import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;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.GenericToStringSerializer;/** * redis配置 * @author 追到乌云的尽头找太阳(Jacob) **/@Configurationpublic class RedisConfig {    @Bean    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {        RedisTemplate redisTemplate = new RedisTemplate<>();        redisTemplate.setConnectionFactory(redisConnectionFactory);        // 使用 GenericFastJsonRedisSerializer 替换默认序列化        GenericFastJsonRedisSerializer genericFastJsonRedisSerializer = new GenericFastJsonRedisSerializer();        // 设置key和value的序列化规则        redisTemplate.setKeySerializer(new GenericToStringSerializer<>(Object.class));        redisTemplate.setValueSerializer(genericFastJsonRedisSerializer);        // 设置hashKey和hashValue的序列化规则        redisTemplate.setHashKeySerializer(new GenericToStringSerializer<>(Object.class));        redisTemplate.setHashValueSerializer(genericFastJsonRedisSerializer);        // 设置支持事物        redisTemplate.setEnableTransactionSupport(true);        redisTemplate.afterPropertiesSet();        return redisTemplate;    }}

RedisTemplate序列化问题

序列化与反序列化规则不一致,导致报错问题

1、配置redisTemplate

                                                                                                                                                                                                                                                                                                                        

2、存值

此次存值,使用redisTemplate的回调函数,是按照字符串序列化方式存redisValue

    public void testRedisListPush() {        String redisKey = "testGoodsKey";        List redisValues = Arrays.asList("10002001", "10002002");        // 使用管道向redis list结构中批量插入元素        redisTemplate.executePipelined((RedisConnection redisConnection) -> {            // 打开管道            redisConnection.openPipeline();            // 给本次管道内添加,一次性执行的多条命令            for (String redisValue : redisValues) {                redisConnection.rPush(redisKey.getBytes(), redisValue.getBytes());            }            return null;        });    }

redis客户端:value是字符串

3、取值

此次取值,返回结果默认是按照 1、配置redisTemplate中配置的JdkSerializationRedisSerializer序列化方式,由于存和取的序列化方式不统一,会产生报错情况。

    public void testRedisListPop() {        String redisKey = "testGoodsKey";        // 使用管道从redis list结构中批量获取元素        List objects = redisTemplate.executePipelined((RedisConnection redisConnection) -> {            // 打开管道            redisConnection.openPipeline();            for (int i = 0; i < 2; i++) {                redisConnection.rPop(redisKey.getBytes());            }            return null;        });        System.out.println(objects);    }

报错详情:反序列化失败


org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.StreamCorruptedException: invalid stream header: 31303030
...
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.StreamCorruptedException: invalid stream header: 31303030
at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:78)
at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:36)
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:80)
... 39 more
Caused by: java.io.StreamCorruptedException: invalid stream header: 31303030
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:899)
at java.io.ObjectInputStream.(ObjectInputStream.java:357)
at org.springframework.core.ConfigurableObjectInputStream.(ConfigurableObjectInputStream.java:63)
at org.springframework.core.ConfigurableObjectInputStream.(ConfigurableObjectInputStream.java:49)
at org.springframework.core.serializer.DefaultDeserializer.deserialize(DefaultDeserializer.java:68)
at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:73)
... 41 more

解决办法

1、取值

需要在redisTemplate.executePipelined入参中再加一个参数:redisTemplate.getStringSerializer(),取值成功,解决问题!!

    public void testRedisListPop() {        String redisKey = "testGoodsKey";        // 使用管道从redis list结构中批量获取元素        List objects = redisTemplate.executePipelined((RedisConnection redisConnection) -> {            // 打开管道            redisConnection.openPipeline();            for (int i = 0; i < 2; i++) {                redisConnection.rPop(redisKey.getBytes());            }            return null;        }, redisTemplate.getStringSerializer());        System.out.println(objects);    }

总结

1、使用原生redisTemplate操作数据和redisTemplate回调函数操作数据注意点:

a.原生redisTemplate操作数据

代码

    public void testRedisListPush() {        String redisKey = "testGoodsKey";        List redisValues = Arrays.asList("10002001", "10002002");        redisValues.forEach(redisValue -> redisTemplate.opsForList().rightPush(redisKey, redisValue));    }

redis客户端数据展示

b.redisTemplate回调函数操作数据

代码

    public void testRedisListPush() {        String redisKey = "testGoodsKey";        List redisValues = Arrays.asList("10002001", "10002002");        // 使用管道向redis list结构中批量插入元素        redisTemplate.executePipelined((RedisConnection redisConnection) -> {            // 打开管道            redisConnection.openPipeline();            // 给本次管道内添加,一次性执行的多条命令            for (String redisValue : redisValues) {                redisConnection.rPush(redisKey.getBytes(), redisValue.getBytes());            }            return null;        });    }

redis客户端数据展示

c.不同点:

原生redisTemplate操作数据序列化方式是和redis配置统一的,redisTemplate回调函数操作数据序列化方式是自定义的。存值取值是需要注意。

到此,关于"Redis中RedisTemplate怎么配置序列和反序列化"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

序列 数据 配置 管道 方式 策略 封装 元素 函数 工具 结构 问题 学习 支持 之间 同时 字符 字符串 客户 客户端 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 数据库工程师 招聘 adk服务器是什么意思 云保互联网科技公司介绍 世界互联网领先的科技成果 数据库建库员DBD 软件开发大赛开班仪式 找个手机软件开发的工作 戴尔r750服务器报价单 服务器硬盘容量怎么看 计算机网络技术论文框架学习 网络安全管理制度与规则 南昌定制软件开发解决方案 广东小溪互联网科技发展公司 微软服务器系统可以当桌面吗 计算机三级网络技术成绩 债权管理软件开发公司 河南品质软件开发服务价钱 美国外贸抗投诉服务器租用 青海智慧养老软件开发专业制作 拳皇忘记登录服务器怎么办 数据库设计用什么字段好 软件开发资质申请 全城有哒网络技术有限公司 bac文件恢复数据库 手机网络安全微电影 网游服务器的安全和稳定性 中铝集团网络安全 湖南网络技术学院一年要多少费用 excel图片与数据库 高密服务器功率多少
0