前文:SpringBoot引入RabbitMQ(一):引入進SpringBoot中
在前文中,就出現過一次無法發送消息的問題
原因:SpringBoot在啟動時,就會自動生成配置好的Queue、Exchange、Key等等,但是如果初次啟動時只有生產者或者消費者的情況下,並不會建立他們,所以發送消息失敗。
解決:生產者、消費者都配置好之后,逐一啟動即可自動生成,然后就可以正常發送消息了
現在生產者、消費者分開放在兩個Demo中,再模擬一下收發消息
生產者:
原項目做生產者,具體搭建方法參考上文
OutSendMessageDTO
package com.zyuan.boot.rabbitmq.message.dto;
@Data public class OutSendMessageDTO implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String messageInfo; }
MqConstant
public class MqConstant {public static final String OUT_SEND_MESSAGE_QUEUE = "outSendMessageQueue"; public static final String OUT_SEND_MESSAGE_EXCHANGE = "outSendMessageExchange"; public static final String OUT_SEND_MESSAGE_KEY = "outSendMessageKey"; }
OutSendMessageProducer
import com.zyuan.boot.rabbitmq.message.constant.MqConstant; import com.zyuan.boot.rabbitmq.message.dto.OutSendMessageDTO; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class OutSendMessageProducer { @Autowired private RabbitTemplate rabbitTemplate; public void sendOutMessage(OutSendMessageDTO outSendMessageDTO) { System.out.println("外發了一條消息"); try { rabbitTemplate.convertAndSend(MqConstant.OUT_SEND_MESSAGE_EXCHANGE, MqConstant.OUT_SEND_MESSAGE_KEY, outSendMessageDTO); System.out.println("外發消息成功"); } catch (Exception e) { System.out.println("外發消息失敗"); e.printStackTrace(); } } }
測試類:
@SpringBootTest @RunWith(SpringRunner.class) public class RabbitMqTest { @Autowired private OutSendMessageProducer outSendMessageProducer;
@Test public void sendOutMessage() { OutSendMessageDTO outSendMessageDTO = new OutSendMessageDTO(); outSendMessageDTO.setId(9999999L); outSendMessageDTO.setMessageInfo("這是外發的消息"); outSendMessageProducer.sendOutMessage(outSendMessageDTO); } }
消費者:
將OutSendMessageDTO、MqConstant復制過來
OutSendMessageConsumer
import com.rabbitmq.client.Channel; import com.zyuan.boot.rabbitmqconsum.message.constant.MqConstant; import com.zyuan.boot.rabbitmqconsum.message.dto.OutSendMessageDTO; import org.springframework.amqp.core.Message; import org.springframework.amqp.rabbit.annotation.*; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.stereotype.Component; import java.io.IOException; @Component public class OutSendMessageConsumer { @RabbitListener( bindings = { @QueueBinding( value = @Queue(value = MqConstant.OUT_SEND_MESSAGE_QUEUE), exchange = @Exchange(value = MqConstant.OUT_SEND_MESSAGE_EXCHANGE), key = MqConstant.OUT_SEND_MESSAGE_KEY ) } ) public void consumeFirstMessage(@Payload OutSendMessageDTO outSendMessageDTO, Channel channel, Message message) { System.out.println("消費到了外發的信息:" + outSendMessageDTO.toString()); try { channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); } catch (IOException e) { e.printStackTrace(); } } }
消息測試:
運行測試類,生產者開始發送消息:
發送成功
但是切到消費者項目查看控制台發現報錯了:
往下翻發現問題點:
可以發現,明明是復制過來的DTO對象,為什么會找不到對象呢
其實在真正的項目開發時,生產者、消費者使用的對象都是同一個,假如生產者創建了這個Message對象,那么應該通過打包、消費者引入Jar包的方式來使用這個對象
所以問題點就顯而易見了:
package路徑不同,導致序列化出現差異,所以報錯
解決:
將消費者的DTO路徑改為與生產者一致
再次進行收發消息:
成功消費了消息
拓展:在實際開發中,可能會配置MessageConverter,但是不同項目之間可能不同,比如生產者使用SimpleMessageConverter,消費者使用Jackson2JsonMessageConverter
那么就會報錯 Json keyword missing,這點要注意