SpringBoot引入RabbitMQ(二):关于无法消费消息的问题
前文: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,这点要注意