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,这点要注意

 

posted @ 2022-04-20 17:15  LonZyuan  阅读(1917)  评论(0编辑  收藏  举报