关于rabbitMQ的初探,自定义对象序列化异常

在SpringBoot结合RabbitMQ的环境下,解决生产者与消费者间因对象序列化导致的错误,通过共享对象定义或使用JSON转换实现跨项目通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在springboot2.1.4结合rabbitMQ3.7.7,通过生产者发送自动义订单对象Order, 消费者消费订单对象的数据,由于数据需要跨网络传输,在生产者端的Order对象需要进行序列化操作,实现了java的原生态序列化接口Serialable, 在设置了queue和exchange之间的绑定关系之后,当生产者发送消息到队列,消费者根据绑定的规则 去到对应的Queue获取数据,结果报错,异常信息如下:

org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Listener method could not be invoked with the incoming message
Endpoint handler details:
Method [public void com.rabbit.producer.RabbitProducer.receiver.OrderRecevier.onOrderMessage(com.rabbit.producer.RabbitProducer.entity.Order,com.rabbitmq.client.Channel,java.util.Map<java.lang.String, java.lang.Object>) throws java.lang.Exception]
Bean [com.rabbit.producer.RabbitProducer.receiver.OrderRecevier@600b7b3d]
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:185) ~[spring-rabbit-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:120) ~[spring-rabbit-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1414) ~[spring-rabbit-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1337) ~[spring-rabbit-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1324) ~[spring-rabbit-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1303) ~[spring-rabbit-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:817) [spring-rabbit-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:801) [spring-rabbit-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$700(SimpleMessageListenerContainer.java:77) [spring-rabbit-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1042) [spring-rabbit-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_71]
Caused by: org.springframework.messaging.converter.MessageConversionException: Cannot convert from [com.rabbit.Springboot4RabbitMQ.entity.Order] to [com.rabbit.producer.RabbitProducer.entity.Order] for GenericMessage [payload=Order [id=RabbitMQTestId0002, name=HelloWorld, messageId=1538919928275$0836e0e7-4976-457e-92fb-44b937255855], headers={amqp_receivedDeliveryMode=PERSISTENT, amqp_receivedRoutingKey=order.ABC, amqp_receivedExchange=order-exchange, amqp_deliveryTag=1, amqp_consumerQueue=order-queue, amqp_redelivered=false, id=0ffe4dcd-048f-f274-bca9-5550f9ecebb1, amqp_consumerTag=amq.ctag-82Oo3kl1I138E2pvVRsczA, contentType=application/x-java-serialized-object, timestamp=1538919929083}]
	at org.springframework.messaging.handler.annotation.support.PayloadArgumentResolver.resolveArgument(PayloadArgumentResolver.java:144) ~[spring-messaging-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:116) ~[spring-messaging-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:137) ~[spring-messaging-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:109) ~[spring-messaging-5.0.8.RELEASE.jar:5.0.8.RELEASE]
	at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:51) ~[spring-rabbit-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:182) ~[spring-rabbit-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	... 10 common frames omitted

2018-10-07 21:45:29.111  WARN 5264 --- [cTaskExecutor-2] ingErrorHandler$DefaultExceptionStrategy : Fatal message conversion error; message 

主要是我的生产者和消费者是两个单独的project,所以说在生产者和消费者端的Order对象是来自于两个类,所以会报错序列化error了,解决方案一:把在consumer的project里面引入producer的依赖。方案二:则是将对象转化为json.在生产者和消费者之间进行一个转化则完成解决上面的出错。  ↵

 

 

<think>好的,我现在需要帮助用户了解如何在RabbitMQ中实现和使用自定义序列化方式。首先,用户提到了他们之前看到的引用内容,这些引用主要涉及使用Gson或Jackson来替代默认的序列化工具,比如SimpleMessageConverter。用户的问题集中在如何实现自定义序列化,所以需要根据这些引用信息来构建答案。 首先,我需要回忆一下RabbitMQ序列化机制。默认情况下,RabbitMQ使用SimpleMessageConverter,它只能处理字节数组、字符串等简单类型,对于自定义对象需要实现Serializable接口。但用户可能不想依赖Java原生序列化,而是想用JSON或者其他格式,比如Gson或Jackson,这样更通用和高效。 接下来,根据引用[1],用户提到了在Provider端配置RabbitTemplate,设置自定义的MessageConverter,比如GsonMqMessageConverter。引用[2]和[3]则展示了使用Jackson2JsonMessageConverter的例子,并且提到需要生产者和消费者都配置相同的转换器。因此,实现自定义序列化的关键步骤应该是创建自定义的MessageConverter,并在生产者和消费者的RabbitTemplate中配置它。 需要详细说明如何创建这些转换器。例如,使用Gson的话,可能需要自己实现MessageConverter接口,或者继承现有的类,覆盖相关方法。而使用Jackson的话,可以直接使用Spring提供的Jackson2JsonMessageConverter,这样更简单。此外,还要注意,如果使用不同的序列化方式,比如Gson和Jackson,生产者和消费者必须使用相同的配置,否则会出现反序列化错误。 然后,需要考虑配置的步骤。在Spring Boot中,通常通过@Bean注解来定义RabbitTemplate和MessageConverter。用户需要在自己的配置类中声明这些Bean,并确保它们被正确注入。例如,在生产者端,配置RabbitTemplate的messageConverter属性为自定义的转换器;同样,在消费者端,也需要配置对应的MessageConverter,这样监听器才能正确解析消息。 另外,引用[3]提到了让自定义对象实现Serializable接口,但用户可能更倾向于使用JSON序列化,这样就不需要实现Serializable。不过,如果用户同时配置了Jackson2JsonMessageConverter,即使对象没有实现Serializable,也能正常工作,因为Jackson会处理对象序列化。这一点可能需要澄清,避免用户混淆。 还需要注意一些潜在的问题,比如生产者和消费者使用不同的序列化方式会导致反序列化失败,或者消息格式不兼容。因此,在步骤中需要强调配置一致性的重要性。此外,可能还需要提到如何测试自定义序列化是否生效,比如发送一个自定义对象消息,并检查消费者是否能正确接收并解析。 最后,根据用户提供的示例,他们可能需要具体的代码示例,比如如何用Gson或Jackson来配置转换器。同时,用户可能想知道不同的序列化方式之间的优缺点,比如Gson和Jackson在性能或灵活性上的差异,但这个问题可能属于后续的问题,如相关问题的部分。 总结一下,回答的结构应该是: 1. 说明默认序列化方式的限制。 2. 实现自定义序列化的步骤:创建MessageConverter,配置生产者和消费者。 3. 提供具体示例,如使用Jackson或Gson。 4. 注意事项,如配置一致性、不需要实现Serializable等。 5. 相关问题,引导用户进一步了解。 现在需要组织语言,确保步骤清晰,代码示例正确,并且引用相关的引用内容。例如,在配置生产者时,引用[1]中的代码示例,而在配置消费者时,引用[2]和[3]中的内容。同时,需要指出两种方法(Gson和Jackson)的不同实现方式,以及它们的配置方法。</think>### RabbitMQ 自定义序列化实现与使用方法 #### 一、默认序列化的局限性 RabbitMQ 默认使用 $SimpleMessageConverter$ 处理消息序列化,仅支持字符串、字节数组等基础类型。若直接传递自定义对象会遇到以下问题: - **类型限制**:需强制实现 $Serializable$ 接口[^3] - **兼容性差**:Java原生序列化对跨语言场景不友好 - **可读性低**:二进制格式难以调试 #### 二、实现自定义序列化的步骤 ##### 1. 创建自定义消息转换器 **方案1:使用 Jackson(推荐)** ```java // 消费者和生产者需配置相同的转换器 @Bean public MessageConverter jacksonMessageConverter() { return new Jackson2JsonMessageConverter(); } ``` **方案2:使用 Gson(需自定义实现)** ```java public class GsonMqMessageConverter extends AbstractMessageConverter { private final Gson gson = new Gson(); @Override protected Message createMessage(Object object, MessageProperties messageProperties) { String json = gson.toJson(object); return new Message(json.getBytes(), messageProperties); } @Override public Object fromMessage(Message message) { return gson.fromJson(new String(message.getBody()), Object.class); } } ``` ##### 2. 配置生产者端 ```java @Bean public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { RabbitTemplate template = new RabbitTemplate(connectionFactory); template.setMessageConverter(jacksonMessageConverter()); // 或 new GsonMqMessageConverter() return template; } ``` 通过 $RabbitTemplate$ 发送消息时自动应用序列化: ```java rabbitTemplate.convertAndSend("exchange", "routingKey", new CustomObject()); ``` ##### 3. 配置消费者端 ```java @Bean public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) { SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); factory.setConnectionFactory(connectionFactory); factory.setMessageConverter(jacksonMessageConverter()); // 必须与生产者一致 return factory; } ``` 消费者监听方法直接接收对象: ```java @RabbitListener(queues = "myQueue") public void handleMessage(CustomObject obj) { // 处理反序列化后的对象 } ``` #### 三、关键注意事项 1. **一致性要求**:生产者和消费者必须使用相同类型的消息转换器[^2][^3] 2. **类型识别**:Jackson需通过 $@ClassMapper$ 处理多态类型,或发送方附加类型信息 3. **性能优化**:Jackson的 $Jackson2JsonMessageConverter$ 默认启用缓存,优于自定义Gson实现 4. **调试技巧**:启用消息追踪插件可查看序列化后的JSON格式 #### 四、配置验证方法 发送包含嵌套结构的测试对象: ```java public class TestObject { private String name; private List<Integer> values; // 需提供无参构造器 + getter/setter } ``` 通过管理界面查看队列消息是否以JSON格式存储: $$ \{ "name": "test", "values": [1,2,3] \} $$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值