RabbitMQ 消息对象 序列化/反序列化 天坑!异常处理方案

目录

[1. 报错的背景](#1. 报错的背景)

[2. 问题分析](#2. 问题分析)

[3. 最佳解决办法](#3. 最佳解决办法)


1. 报错的背景

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

b)这里有一个前提:我清楚使用 org.springframework.amqp.rabbit.core.RabbitTemplate 来发送消息到 RabbitMQ 队列时,消息的序列化是由 MessageConverter 完成的。默认情况下,RabbitTemplate 使用 SimpleMessageConverter,它只能处理简单的消息类型(如整形、字符串、字节数组等),如果一旦是类似于 map 这种复杂结构,则需要配置一个适当的 MessageConverter 来序列化和反序列化这些对象。

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

XML 复制代码
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
java 复制代码
@Configuration
public class MqConfig {

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

}

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

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,结果报错......

网上也搜过这种情况,发现好像还没有人提出怎么解决这种情况...

3. 最佳解决办法

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

发送消息如下:

接收消息如下:

成功解决异常!

相关推荐
Pniubi2 小时前
分布式锁分类讲解
分布式
nvd113 小时前
深入剖析:GCP Pub/Sub 与 Apache Kafka 对消息处理延迟与消费者卡死的处理机制异同
分布式·kafka·apache
我不是阵雨4 小时前
分布式事务难题与实战解法全解析
分布式·微服务·架构
song5014 小时前
React Native for OpenHarmony 实战:三方库 react-native-parallax-scroll-view 的鸿蒙化适配指南
分布式·react native·react.js·transformer·harmonyos
做个文艺程序员6 小时前
MQ第03篇:RabbitMQ进阶实战:Topic路由+死信队列+延迟消息,SaaS订单超时取消完整方案
分布式·消息队列·rabbitmq·死信队列·延迟队列
风花一世月7 小时前
[特殊字符] 我把一套分布式消防方案做成了能跑的 3D 沙盘(三架无人机共用一根水带,在线直接玩)
分布式·3d·ai·无人机
我不是阵雨9 小时前
如何拿捏分布式四大模式?
分布式
吴声子夜歌11 小时前
Docker入门与实战——实战案例(分布式处理与大数据平台)
大数据·分布式·docker
bksczm11 小时前
Redis基础篇之初识分布式
数据库·redis·分布式
此时不提桶,更待何时21 小时前
06-18-A-RabbitMQ消息特性与消费机制详解
分布式·rabbitmq