Skip to content

我们在RabbitMQConfig中将交换机名称以及队列名称都定死了,那么我们此时如果有多个业务都需要用到MQ,例如用户下单时需要超时关单,用户退款时需要回退优惠券,这些业务该怎样处理呢?

核心就是我们需要让监听器能够判断出当前是什么消息,已知交换机名称以及队列名称在当前配置下是无法更改的,那么我们需要一个“动态参数”来标明传递过来的是什么参数,我想到的有两种方案。

  1. 消息体携带信息,判断当前是超时关单的消息还是回退优惠券的消息,然后再来处理业务逻辑
  2. 交换机名称以及队列名称是不变的,但是“路由键”是变化的,我们可以根据路由键来判断消息类型
  3. 投递到新的队列中去,把不同的消息投递到不同的队列,点击查看详细配置

消息体携带信息判断当前消息类型

创建消息类,用于发送和接收消息,注意要实现Serializable接口,不实现会报错哦。

java
@Data
public class CommonMQMsg implements Serializable {

    private String type;

    private String msg;
}

先来看发送消息,发送CommonMQMsg对象构成的数据。

java
@SpringBootTest
class RabbitmqDemoApplicationTests {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    void send() {
        CommonMQMsg msg = new CommonMQMsg();
        msg.setType("order.refund");
        msg.setMsg("新订单来啦!!");

        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME, "order.new", msg);
    }
}

再来看接收消息,使用 CommonMQMsg 接收消息,框架会自动帮我们转换消息格式。

java
@Component
@RabbitListener(queues = "order_queue") // 监听的队列名称
public class OrderMQListener {

    @RabbitHandler
    public void releaseCouponRecord(CommonMQMsg commonMQMsg, Message message) throws IOException {
        if ("order.new".equals(commonMQMsg.getType())) {
            log.info("处理新订单逻辑");
        } else if ("order.refund".equals(commonMQMsg.getType())){
            log.info("处理退款逻辑");
        }
    }
}

根据routingKey判断当前消息类型

先来看消息的发送,order.new就是我们这里的路由Key

java
@Test
void send() {
    rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME, "order.new", "新订单来啦!!");
}

再来看消息消费者的监听,是如何判断的

java
@Component
@RabbitListener(queues = "order_queue") // 监听的队列名称
public class OrderMQListener {

    @RabbitHandler
    public void releaseCouponRecord(String msg, Message message) throws IOException {
        // 获取路由Key
        final String routingKey = message.getMessageProperties().getReceivedRoutingKey();
        if ("order.new".equals(routingKey)) {
            // TODO 处理新订单逻辑
        } else if ("order.refund".equals(routingKey)){
            // TODO 处理退款逻辑
        }
    }
}

说明:这个路由键例如order.new,这些数据建议再项目中使用常量去提前定义,我这里为了讲解清晰就没写了。