RabbitMQ 消息对象通过 Jackson 库消息转化器 序列化/反序列化 天坑!

这篇具有很好参考价值的文章主要介绍了RabbitMQ 消息对象通过 Jackson 库消息转化器 序列化/反序列化 天坑!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1. 报错的背景

2. 问题分析

3. 最佳解决办法


1. 报错的背景

a)使用 RabbitMQ 发送消息时,发送消息的类型为 Map<String, Object>,map 里面我 put 了一个 <String, Long> 类型,如下图:

jackson2jsonmessageconverter,RabbitMQ(从理论到根据源码实现),面试总结,rabbitmq,分布式

b)这里有一个前提:我清楚使用 org.springframework.amqp.rabbit.core.RabbitTemplate 来发送消息到 RabbitMQ 队列时,消息的序列化是由 MessageConverter 完成的。默认情况下,RabbitTemplate 使用 SimpleMessageConverter,基于JDK的ObjectOutputStream完成序列化。 

但是这样的数据就有可能引发以下两种问题:

  1. 转化后数据过长,影响传输效率。
  2. 容易引发 sql 注入问题。

因此这里我使用 Jackson 库将对象序列化为 JSON 格式,如下消息转化器配置

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
@Configuration
public class MqConfig {

    /**
     * 消息转化器
     * @return
     */
    @Bean
    public MessageConverter jsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

}

c)拿到发来的消息 map 后,将消息按照传入的类型进行强制类型转化, 但是在强制类型转化 Long 的时候,出现了以下错误:

jackson2jsonmessageconverter,RabbitMQ(从理论到根据源码实现),面试总结,rabbitmq,分布式

jackson2jsonmessageconverter,RabbitMQ(从理论到根据源码实现),面试总结,rabbitmq,分布式

jackson2jsonmessageconverter,RabbitMQ(从理论到根据源码实现),面试总结,rabbitmq,分布式

2. 问题分析

a)在 Map<String, Object> 中传入 <String, Long> 类型作为消息并转发,接着接收到消息后,再从 Map 中取出 <String, Long> (由于是 Object 类型,所以需要强制类型转化),然后强制类型转化 Long 引发异常,原因是 “Integer 类型不能被转化为 Long”,可是我明明传入的 Long 啊???

b)经过调试,也发现,RabbitMQ 监听到消息之后,Map 中原本是 Long 的数据,确实变成了 Integer 类型......

c)接着,又尝试了以下两种办法:

  1. 传入<String, Long>,接收到消息后,强制类型转化的时候就转为 <String,Integer>,解决了报错问题,但是引入了新的问题:“这不就丢失了 Long 的精度吗???”.
  2. 直接传入一个实体类对象(继承了 Serializable 接口),塞入 Long 数据,然后发送消息,解决了报错问题,可是总不能每次遇到 Long 类型都传一个实体类对象吧......
  3. 自己通过 ObjectMapper 的 writeValueAsString 转化为 JSON,然后接收消息之后再通过 readValue 将 JSON 反序列化成 Map,结果报错......

d)最后,我自己又重新写了一个 demo,模拟这个场景。但不同的是,为了验证是 rabbitmq 自身的消息转换问题,还是我引入的 Jackson 库有问题,因此这里我没有引入 Jackson 库又试了一次,发现成功了,最后发现,原来是 Jackson 库配置消息转化器的问题(b 站上的黑马程序员教程,讲错了).

为什么呢?因为 Jackson 库中的消息转化器只是基于 ObjectMapper 的 readValue 进行了一层转化,例如转化出 HashMap,但是对于你 HashMap 中存在复杂类型,例如 Long,就不能直接通过 get 获取(Jackson 库中的消息转化器没有对这一步做处理),而是需要通过 ObjectMapper 中的 convertValue 进行进一步的转化才行~

3. 解决办法

3.1. 方法一(可破头都要用 Jackson 的消息转化器)

那干脆这样做:在每次 Map<String, Object> 中有 Long 类型的时候,都先将 Long 类型通过 toString() 转化为字符串,然后接收到消息的时候,先强转为 String,然后再通过 Long.valueOf() 转化为 Long 类型,既解决了异常,又保证了不丢失精度.

发送消息如下:

jackson2jsonmessageconverter,RabbitMQ(从理论到根据源码实现),面试总结,rabbitmq,分布式

接收消息如下:

jackson2jsonmessageconverter,RabbitMQ(从理论到根据源码实现),面试总结,rabbitmq,分布式

成功解决异常!

3.2、方法二(推荐)

不要使用 Jackson 库中的消息转化器,而是使用 Jackson 库中的 ObjectMapper (不用添加任何依赖)手动完成序列化和反序列化的过程.

  1. 发送消息前,不用将 Long 类型转化成 String,只需要通过 ObjectMapper 中的 writeValueAsString 转化成 JSON 格式后再发送消息. 
  2. 拿到消息后先通过 readValue 拿到 map ,对于 Long 这种复杂类型,直接通过 ObjectMapper.convertValue 进一步解析,就可以得到了.

        Long visits = objectMapper.convertValue(hashMap.get("visits"), new TypeReference<Long>() {});

jackson2jsonmessageconverter,RabbitMQ(从理论到根据源码实现),面试总结,rabbitmq,分布式文章来源地址https://www.toymoban.com/news/detail-852376.html

到了这里,关于RabbitMQ 消息对象通过 Jackson 库消息转化器 序列化/反序列化 天坑!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Jackson标签的高阶使用样例--多继承/子类、对象id、JsonIdentityInfo、JsonTypeInfo、JsonSubTypes

    最近笔者在开发 大数据平台XSailboat 的 数据资产目录 模块。它的其中一个功能是能定义并查看资产数据。我们支持的资产类型不仅有关系数据库表,也支持Kafka主题,hdfs上的文件等。对于Kafka主题,hdfs文件等,它们没有强模式约束和描述,但为了理解、查看和约束其中的结构

    2024年01月18日
    浏览(30)
  • idea插件(四)-- GsonFormatPlus(JSON对象转化JavaBean对象)

    目录 1. 安装 2. 快捷键操作 3. 操作说明 拓展:生成实体类的成员变量的形式进行Setting Alt + S   最后生成的效果如下:  注意: 勾选选项 勾选效果 A 回弹出一个窗口,便于对预生成的字段进行检查与修改(字段注释的添加可以在此窗口进行修改)。 B 勾选后,如有嵌套的对象

    2024年02月03日
    浏览(34)
  • JSON 与 Java 对象之间的转化

    在现在的日常开发中,不管前端还是后端,JSON 格式的数据是用得比较多的,甚至可以说无处不在。 接触最多的就是 POST 请求中传递的数据一般以 JSON 的格式放在请求体中,而且服务端各种 API 返回的数据,在响应体中也基本都是以 JSON 格式的数据进行返回的,这也是 RESTfu

    2024年01月17日
    浏览(42)
  • 如何把实体类对象转化为json(json转实体类对象)​

    使用fastjson框架解决实体类转json的问题(实体类要序列化哦,如  实体类  ) 1、序列化(实体类转json,text为json数据,user为实体类,JSON.toJSONString为固定写法) 2、反序列化(json转实体类,text为json数据,User为实体类,JSON.parseObject为固定写法) 点击下载jar

    2024年02月10日
    浏览(31)
  • 如何将JSON字符串转化成对象

    在这里只能使用ObjiectMapper这个类才能将Json字符串转成对象的格式进行输出 话不多说,直接上代码 注意事项: json字符串只能匹配上实体类里面定义的属性,没有被定义的属性是无法进行匹配赋值的

    2024年02月13日
    浏览(43)
  • instanceof、对象类型转化、static关键字

    instanceof是判断一个对象是否与一个类有关系的   先看引用类型,再看实际类型 * 例子:obj instanceof A 先看obj的类型是否与A有关联,无关联则报错,有关联则判断obj的实际类型 因为obj的实际类型是son,所以String类与他无关,所以返回false 对象类型转换: 发生在父子之间

    2024年02月02日
    浏览(37)
  • 前端处理后端传来的Long型数据精度丢失的问题--对象转换器Jackson0bjectMapper

    1、问题描述 前端提交参数 后端处理 前端js对long型数据进行处理时丢失精度(只能保证16位),导致提交的id和数据库中的id不一致。 2、 问题实现 如何解决这个问题? 我们可以在服务端给页面响应json数据时进行处理,将long型数据统一转为String字符串 3、具体代码实现–对象

    2024年02月16日
    浏览(46)
  • JAVA 字符串JSON Map 对象转化

    目录 字符串转JSON JSON 转字符串 json字符串转map 将map转成json字符串 map转对象 将对象转化成map 将对象转化成JSON Json转对象 方式一 第一步 将map 转成json字符串对象 第二步 将json字符串对象转化成对象 第一步 将对象转化成json字符串 第二步 将JSON字符串转成map 方法一:fastjson转

    2024年02月15日
    浏览(56)
  • javascript中json 对象 数组之间相互转化的示例

    在JavaScript中,你可以使用 JSON.stringify() 将JSON对象转换为JSON字符串,使用 JSON.parse() 将JSON字符串转换为JSON对象。而要将JSON对象转换为数组,可以使用 Object.values() 方法,而要将数组转换为JSON对象,可以使用 Array.reduce() 方法。下面是这些转换的示例代码: 将JSON对象转换为J

    2024年02月16日
    浏览(33)
  • 07、如何取出对象数组里的固定 key 值来拼成一个对象(以及对象与数组之间的转化)

    其一、从后端拿到的数据为: let arr = [1, 3, 7, 24] 其二、目标数据为(即:后台需要下发的数据): {vlan_1: 1, vlan_3: 1, vlan_7: 1, vlan_24: 1} 其一、定义一个动态的 key 值来满足业务需求: vlan_X : A、代码展示: B、结果展示: 其二、通过 map 操作,获取目标对象: A、代码展示: B、结果

    2024年02月06日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包