rabbitMQ入门 (mac)

一.安装

  1. ‌**使用 Homebrew 安装(推荐)**‌:

    • 打开终端,运行以下命令:
    复制代码

    bashCopy Code

    # 安装 RabbitMQ brew install rabbitmq # 启动 RabbitMQ 服务 brew services start rabbitmq

  2. 配置环境变量‌:

    • 将 RabbitMQ 的 sbin 目录添加到 PATH:
    复制代码

    bashCopy Code

    echo 'export PATH="/usr/local/sbin:$PATH"' >> ~/.zshrc source ~/.zshrc

  3. 访问管理界面‌:

    • 启动后访问 http://localhost:15672
    • 默认账号密码:guest/guest
  4. 验证安装‌:

    复制代码

    bashCopy Code

    # 检查 RabbitMQ 状态 rabbitmqctl status

二 .springboot项目集成

复制代码
  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
  </dependency>

三.测试

3.1.封装一个工具类

复制代码
package org.jeecg.boot.starter.rabbitmq.client;


import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.boot.starter.rabbitmq.event.EventObj;
import org.jeecg.boot.starter.rabbitmq.event.JeecgRemoteApplicationEvent;
import org.jeecg.boot.starter.rabbitmq.exchange.DelayExchangeBuilder;
import org.jeecg.common.annotation.RabbitComponent;
import org.jeecg.common.base.BaseMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.bus.BusProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import jakarta.annotation.Resource;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 消息队列客户端
 */
@Slf4j
@Configuration
public class RabbitMqClient {

    private static final Logger logger = LoggerFactory.getLogger(RabbitMqClient.class);

    private final RabbitAdmin rabbitAdmin;

    private final RabbitTemplate rabbitTemplate;


    @Resource
    private SimpleMessageListenerContainer messageListenerContainer;

    @Resource
    BusProperties busProperties;
    @Resource
    private ApplicationEventPublisher publisher;


    @Resource
    private ApplicationContext applicationContext;


    @Bean
    public void initQueue() {
        Map<String, Object> beansWithRqbbitComponentMap = this.applicationContext.getBeansWithAnnotation(RabbitComponent.class);
        Class<? extends Object> clazz = null;
        for (Map.Entry<String, Object> entry : beansWithRqbbitComponentMap.entrySet()) {
            //获取到实例对象的class信息
            clazz = entry.getValue().getClass();
            Method[] methods = clazz.getMethods();
            RabbitListener rabbitListener = clazz.getAnnotation(RabbitListener.class);
            if (ObjectUtil.isNotEmpty(rabbitListener)) {
                log.info("初始化队列....class........rabbitListener=" + rabbitListener);
                createQueue(rabbitListener);
            }
            for (Method method : methods) {
                RabbitListener methodRabbitListener = method.getAnnotation(RabbitListener.class);
                if (ObjectUtil.isNotEmpty(methodRabbitListener)) {
                    log.info("初始化队列...method.........methodRabbitListener=" + methodRabbitListener);
                    createQueue(methodRabbitListener);
                }
            }

        }
    }

    /**
     * 初始化队列
     *
     * @param rabbitListener
     */
    private void createQueue(RabbitListener rabbitListener) {
        String[] queues = rabbitListener.queues();
        DirectExchange directExchange = createExchange(DelayExchangeBuilder.DELAY_EXCHANGE);
        //创建交换机
        rabbitAdmin.declareExchange(directExchange);
        if (ObjectUtil.isNotEmpty(queues)) {
            for (String queueName : queues) {
                Properties result = rabbitAdmin.getQueueProperties(queueName);
                if (ObjectUtil.isEmpty(result)) {
                    Queue queue = new Queue(queueName);
                    addQueue(queue);
                    Binding binding = BindingBuilder.bind(queue).to(directExchange).with(queueName);
                    rabbitAdmin.declareBinding(binding);
                    log.info("创建队列:" + queueName);
                }else{
                    log.info("已有队列:" + queueName);
                }
            }
        }
    }

    /**
     * 创建自定义队列
     *
     * @param queueName 自定义队列名称
     */
    public boolean createQueue(String queueName) {
        DirectExchange directExchange = createExchange(DelayExchangeBuilder.DELAY_EXCHANGE);
        //创建交换机
        rabbitAdmin.declareExchange(directExchange);
        Properties result = rabbitAdmin.getQueueProperties(queueName);
        if (ObjectUtil.isEmpty(result)) {
            Queue queue = new Queue(queueName);
            addQueue(queue);
            Binding binding = BindingBuilder.bind(queue).to(directExchange).with(queueName);
            rabbitAdmin.declareBinding(binding);
            log.info("创建队列:" + queueName);
            return true;
        }else{
            log.info("已有队列:" + queueName);
            return false;
        }
    }

    

    private Map sentObj = new HashMap<>();


    @Autowired
    public RabbitMqClient(RabbitAdmin rabbitAdmin, RabbitTemplate rabbitTemplate) {
        this.rabbitAdmin = rabbitAdmin;
        this.rabbitTemplate = rabbitTemplate;
    }


    /**
     * 发送远程事件
     *
     * @param handlerName
     * @param baseMap
     */
    public void publishEvent(String handlerName, BaseMap baseMap) {
        EventObj eventObj = new EventObj();
        eventObj.setHandlerName(handlerName);
        eventObj.setBaseMap(baseMap);
        publisher.publishEvent(new JeecgRemoteApplicationEvent(eventObj, busProperties.getId()));
    }

    /**
     * 转换Message对象
     *
     * @param messageType 返回消息类型 MessageProperties类中常量
     * @param msg
     * @return
     */
    public Message getMessage(String messageType, Object msg) {
        MessageProperties messageProperties = new MessageProperties();
        messageProperties.setContentType(messageType);
        Message message = new Message(msg.toString().getBytes(), messageProperties);
        return message;
    }

    /**
     * 有绑定Key的Exchange发送
     *
     * @param routingKey
     * @param msg
     */
    public void sendMessageToExchange(TopicExchange topicExchange, String routingKey, Object msg) {
        Message message = getMessage(MessageProperties.CONTENT_TYPE_JSON, msg);
        rabbitTemplate.send(topicExchange.getName(), routingKey, message);
    }

    /**
     * 没有绑定KEY的Exchange发送
     *
     * @param exchange
     * @param msg
     */
    public void sendMessageToExchange(TopicExchange topicExchange, AbstractExchange exchange, String msg) {
        addExchange(exchange);
        logger.info("RabbitMQ send " + exchange.getName() + "->" + msg);
        rabbitTemplate.convertAndSend(topicExchange.getName(), msg);
    }


    /**
     * 发送消息
     *
     * @param queueName 队列名称
     * @param params    消息内容map
     */
    public void sendMessage(String queueName, Object params) {
        log.info("发送消息到mq");
        try {
            rabbitTemplate.convertAndSend(DelayExchangeBuilder.DELAY_EXCHANGE, queueName, params, message -> {
                return message;
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送消息
     *
     * @param queueName 队列名称
     */
    public void sendMessage(String queueName) {
        this.send(queueName, this.sentObj, 0);
        this.sentObj.clear();
    }


    public RabbitMqClient put(String key, Object value) {
        this.sentObj.put(key, value);
        return this;
    }

    /**
     * 延迟发送消息
     *
     * @param queueName  队列名称
     * @param params     消息内容params
     * @param expiration 延迟时间 单位毫秒
     */
    public void sendMessage(String queueName, Object params, Integer expiration) {
        this.send(queueName, params, expiration);
    }

    private void send(String queueName, Object params, Integer expiration) {
        Queue queue = new Queue(queueName);
        addQueue(queue);
        CustomExchange customExchange = DelayExchangeBuilder.buildExchange();
        rabbitAdmin.declareExchange(customExchange);
        Binding binding = BindingBuilder.bind(queue).to(customExchange).with(queueName).noargs();
        rabbitAdmin.declareBinding(binding);
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        log.debug("发送时间:" + sf.format(new Date()));
        rabbitTemplate.convertAndSend(DelayExchangeBuilder.DEFAULT_DELAY_EXCHANGE, queueName, params, message -> {
            if (expiration != null && expiration > 0) {
                message.getMessageProperties().setHeader("x-delay", expiration);
            }
            return message;
        });
    }


    /**
     * 给queue发送消息
     *
     * @param queueName
     */
    public String receiveFromQueue(String queueName) {
        return receiveFromQueue(DirectExchange.DEFAULT, queueName);
    }

    /**
     * 给direct交换机指定queue发送消息
     *
     * @param directExchange
     * @param queueName
     */
    public String receiveFromQueue(DirectExchange directExchange, String queueName) {
        Queue queue = new Queue(queueName);
        addQueue(queue);
        Binding binding = BindingBuilder.bind(queue).to(directExchange).withQueueName();
        rabbitAdmin.declareBinding(binding);
        String messages = (String) rabbitTemplate.receiveAndConvert(queueName);
        System.out.println("Receive:" + messages);
        return messages;
    }

    /**
     * 创建Exchange
     *
     * @param exchange
     */
    public void addExchange(AbstractExchange exchange) {
        rabbitAdmin.declareExchange(exchange);
    }

    /**
     * 删除一个Exchange
     *
     * @param exchangeName
     */
    public boolean deleteExchange(String exchangeName) {
        return rabbitAdmin.deleteExchange(exchangeName);
    }


    /**
     * 声明其名称自动命名的队列。它是用exclusive=true、autoDelete=true和 durable = false
     *
     * @return Queue
     */
    public Queue addQueue() {
        return rabbitAdmin.declareQueue();
    }

    /**
     * 创建一个指定的Queue
     *
     * @param queue
     * @return queueName
     */
    public String addQueue(Queue queue) {
        return rabbitAdmin.declareQueue(queue);
    }

    /**
     * 删除一个队列
     *
     * @param queueName the name of the queue.
     * @param unused    true if the queue should be deleted only if not in use.
     * @param empty     true if the queue should be deleted only if empty.
     */
    public void deleteQueue(String queueName, boolean unused, boolean empty) {
        rabbitAdmin.deleteQueue(queueName, unused, empty);
    }

    /**
     * 删除一个队列
     *
     * @param queueName
     * @return true if the queue existed and was deleted.
     */
    public boolean deleteQueue(String queueName) {
        return rabbitAdmin.deleteQueue(queueName);
    }

    /**
     * 绑定一个队列到一个匹配型交换器使用一个routingKey
     *
     * @param queue
     * @param exchange
     * @param routingKey
     */
    public void addBinding(Queue queue, TopicExchange exchange, String routingKey) {
        Binding binding = BindingBuilder.bind(queue).to(exchange).with(routingKey);
        rabbitAdmin.declareBinding(binding);
    }

    /**
     * 绑定一个Exchange到一个匹配型Exchange 使用一个routingKey
     *
     * @param exchange
     * @param topicExchange
     * @param routingKey
     */
    public void addBinding(Exchange exchange, TopicExchange topicExchange, String routingKey) {
        Binding binding = BindingBuilder.bind(exchange).to(topicExchange).with(routingKey);
        rabbitAdmin.declareBinding(binding);
    }

    /**
     * 去掉一个binding
     *
     * @param binding
     */
    public void removeBinding(Binding binding) {
        rabbitAdmin.removeBinding(binding);
    }

    /**
     * 创建交换器
     *
     * @param exchangeName
     * @return
     */
    public DirectExchange createExchange(String exchangeName) {
        return new DirectExchange(exchangeName, true, false);
    }
}

3.2服务端测试类

测试5种消息类型:

1.简单模式(Simple Mode)‌

  • 由生产者、队列和消费者组成,生产者将消息发送到队列,消费者从队列消费。

  • 适用于最基础的消息传递场景。

2.‌工作队列模式(Work Queues)‌

  • 多个消费者竞争消费消息,适用于任务分配和负载均衡。

  • 通过basicQos(1)实现消息确认机制,确保消息处理完成后再删除队列中的消息。

队列失败后可设置重入规则,让该消息进入别的消费者

3.‌发布/订阅模式(Publish/Subscribe)‌

  • 生产者将消息发送到交换机,交换机将消息广播到所有绑定的队列。

  • 使用fanout类型交换机实现。

可用于消息总线的开发

rabbitMqClient.publishEvent(CloudConstant.MQ_DEMO_BUS_EVENT, params);

4.‌路由模式(Routing)‌

  • 生产者发送消息时指定路由键(Routing Key),消费者绑定队列时指定相同的路由键才能接收消息。

  • 使用direct类型交换机实现。

可用于不同服务之前的消息收发

rabbitTemplate.convertAndSend(CloudConstant.MQ_ROUTING_EXCHANGE, CloudConstant.MQ_ROUTING_KEY_INFO, infoMap);

5.‌主题模式(Topics)‌

  • 基于路由键的模式匹配,支持通配符(*匹配一个单词,#匹配多个单词)。

  • 使用topic类型交换机实现。

可用于不同业务的手法,比如远洋地产的400客户

rabbitTemplate.convertAndSend(CloudConstant.MQ_TOPIC_EXCHANGE, "order.create", orderMap);

6.‌远程过程调用(RPC)‌

  • 实现请求-响应模式,生产者发送请求消息,消费者处理后返回结果。

  • 通过消息的reply_to属性实现异步通信。

    package org.jeecg.modules.test.rabbitmq.controller;

    import io.swagger.v3.oas.annotations.Operation;
    import io.swagger.v3.oas.annotations.tags.Tag;
    import jakarta.servlet.http.HttpServletRequest;

    import org.jeecg.boot.starter.rabbitmq.client.RabbitMqClient;
    import org.jeecg.common.api.vo.Result;
    import org.jeecg.common.base.BaseMap;
    import org.jeecg.modules.test.rabbitmq.constant.CloudConstant;
    import org.springframework.amqp.rabbit.core.RabbitTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;

    import cn.hutool.core.util.RandomUtil;

    /**

    • RabbitMqClient发送消息

    • @author: zyf

    • @date: 2022/04/21
      */
      @RestController
      @RequestMapping("/sys/test")
      @Tag(name = "【微服务】MQ单元测试")
      public class JeecgMqTestController {

      @Autowired
      private RabbitMqClient rabbitMqClient;

      @Autowired(required = false)
      private RabbitTemplate rabbitTemplate;

      /**

        1. 简单模式(Simple Mode)
      • 由生产者、队列和消费者组成,生产者将消息发送到队列,消费者从队列消费。
      • 适用于最基础的消息传递场景。
      • 架构:Producer -> Queue -> Consumer(单个消费者)
        */
        @GetMapping(value = "/rabbitmq1")
        @Operation(summary = "RabbitMQ简单模式测试")
        public Result<?> rabbitmq1(HttpServletRequest req) {
        BaseMap map = new BaseMap();
        map.put("orderId", RandomUtil.randomNumbers(10));
        map.put("message", "简单模式消息:生产者->队列->单个消费者");
        rabbitMqClient.sendMessage(CloudConstant.MQ_SIMPLE_QUEUE, map);
        return Result.OK("简单模式消息发送成功");
        }

      /**

        1. 工作队列模式(Work Queues)
      • 多个消费者竞争消费消息,适用于任务分配和负载均衡。
      • 通过basicQos(1)实现消息确认机制,确保消息处理完成后再删除队列中的消息。
      • 架构:Producer -> Queue -> Consumer1, Consumer2, Consumer3(多个消费者竞争消费)
      • 观察三个接受者如何分配处理消息:HelloReceiver1、HelloReceiver2、HelloReceiver3,会均衡分配
        */
        @GetMapping(value = "/rabbitmq2")
        @Operation(summary = "RabbitMQ工作队列模式测试")
        public Result<?> rabbitmq2(HttpServletRequest req) {
        BaseMap map = new BaseMap();
        map.put("orderId", "9"+RandomUtil.randomNumbers(10));
        map.put("message", "工作队列模式消息:多个消费者竞争消费");
        rabbitMqClient.sendMessage(CloudConstant.MQ_JEECG_PLACE_ORDER, map);
        return Result.OK("工作队列模式消息发送成功,观察多个消费者如何分配");
        }

      /**

        1. 发布/订阅模式(Publish/Subscribe)
      • 生产者将消息发送到交换机,交换机将消息广播到所有绑定的队列。
      • 使用fanout类型交换机实现。
      • 架构:Producer -> Exchange(fanout) -> Queue1, Queue2, Queue3(所有队列都收到消息)
        */
        @GetMapping(value = "/rabbitmq3")
        @Operation(summary = "RabbitMQ发布/订阅模式测试")
        public Result<?> rabbitmq3(HttpServletRequest req) {
        BaseMap params = new BaseMap();
        params.put("orderId", RandomUtil.randomNumbers(10));
        params.put("message", "发布/订阅模式消息:所有订阅者都能收到");
        rabbitMqClient.publishEvent(CloudConstant.MQ_DEMO_BUS_EVENT, params);
        return Result.OK("发布/订阅模式消息发送成功,所有订阅者都会收到");
        }

      /**

        1. 路由模式(Routing)
      • 生产者发送消息时指定路由键(Routing Key),消费者绑定队列时指定相同的路由键才能接收消息。

      • 使用direct类型交换机实现。

      • 架构:Producer -> Exchange(direct) -> Queue1(routingKey:info), Queue2(routingKey:error)

      • 只有路由键匹配的队列才能收到消息
        */
        @GetMapping(value = "/rabbitmq4")
        @Operation(summary = "RabbitMQ路由模式测试")
        public Result<?> rabbitmq4(HttpServletRequest req) {
        if (rabbitTemplate == null) {
        return Result.error("RabbitTemplate未注入,路由模式需要直接使用RabbitTemplate");
        }

        // 发送info级别的消息
        BaseMap infoMap = new BaseMap();
        infoMap.put("orderId", RandomUtil.randomNumbers(10));
        infoMap.put("level", "info");
        infoMap.put("message", "路由模式消息:info级别");
        rabbitTemplate.convertAndSend(CloudConstant.MQ_ROUTING_EXCHANGE, CloudConstant.MQ_ROUTING_KEY_INFO, infoMap);

        // 发送error级别的消息
        BaseMap errorMap = new BaseMap();
        errorMap.put("orderId", RandomUtil.randomNumbers(10));
        errorMap.put("level", "error");
        errorMap.put("message", "路由模式消息:error级别");
        rabbitTemplate.convertAndSend(CloudConstant.MQ_ROUTING_EXCHANGE, CloudConstant.MQ_ROUTING_KEY_ERROR, errorMap);

        return Result.OK("路由模式消息发送成功(info和error路由键)");
        }

      /**

        1. 主题模式(Topics)
      • 基于路由键的模式匹配,支持通配符(*匹配一个单词,#匹配多个单词)。

      • 使用topic类型交换机实现。

      • 架构:Producer -> Exchange(topic) -> Queue1(routingKey:order.), Queue2(routingKey:payment.)

      • 支持通配符匹配:* 匹配一个单词,# 匹配零个或多个单词
        */
        @GetMapping(value = "/rabbitmq5")
        @Operation(summary = "RabbitMQ主题模式测试")
        public Result<?> rabbitmq5(HttpServletRequest req) {
        if (rabbitTemplate == null) {
        return Result.error("RabbitTemplate未注入,主题模式需要直接使用RabbitTemplate");
        }

        // 发送订单相关消息(匹配 order.*)
        BaseMap orderMap = new BaseMap();
        orderMap.put("orderId", RandomUtil.randomNumbers(10));
        orderMap.put("type", "order");
        orderMap.put("message", "主题模式消息:订单创建");
        rabbitTemplate.convertAndSend(CloudConstant.MQ_TOPIC_EXCHANGE, "order.create", orderMap);

        // 发送支付相关消息(匹配 payment.*)
        BaseMap paymentMap = new BaseMap();
        paymentMap.put("orderId", RandomUtil.randomNumbers(10));
        paymentMap.put("type", "payment");
        paymentMap.put("message", "主题模式消息:支付成功");
        rabbitTemplate.convertAndSend(CloudConstant.MQ_TOPIC_EXCHANGE, "payment.success", paymentMap);

        return Result.OK("主题模式消息发送成功(order.create 和 payment.success)");
        }

      /**

        1. 远程过程调用(RPC)
      • 实现请求-响应模式,生产者发送请求消息,消费者处理后返回结果。

      • 通过消息的reply_to属性实现异步通信。

      • 架构:Client -> Queue -> Server -> Reply Queue -> Client

      • 使用correlationId关联请求和响应
        */
        @GetMapping(value = "/rabbitmq6")
        @Operation(summary = "RabbitMQ RPC模式测试")
        public Result<?> rabbitmq6(HttpServletRequest req) {
        if (rabbitTemplate == null) {
        return Result.error("RabbitTemplate未注入,RPC模式需要直接使用RabbitTemplate");
        }

        BaseMap requestMap = new BaseMap();
        requestMap.put("requestId", RandomUtil.randomNumbers(10));
        requestMap.put("method", "calculate");
        requestMap.put("params", "1+1");
        requestMap.put("message", "RPC模式:请求计算 1+1");

        // 发送RPC请求(实际使用中需要设置reply_to和correlation_id)
        // 这里只是示例,完整的RPC需要配置回调队列和关联ID
        rabbitTemplate.convertAndSend(CloudConstant.MQ_RPC_QUEUE, requestMap);

        return Result.OK("RPC模式请求发送成功(注意:完整的RPC需要配置回调队列)");
        }
        }

3.3客户端测试类

这是只实现一种工作队列模式,不然就得贴8个类了,别的用ai生成一下吧,我也是ai生成测试的。。

复制代码
package org.jeecg.modules.test.rabbitmq.listener;

import org.jeecg.boot.starter.rabbitmq.core.BaseRabbiMqHandler;
import org.jeecg.boot.starter.rabbitmq.listenter.MqListener;
import org.jeecg.common.annotation.RabbitComponent;
import org.jeecg.common.base.BaseMap;
import org.jeecg.modules.test.rabbitmq.constant.CloudConstant;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.web.client.RestTemplate;

import com.rabbitmq.client.Channel;

import lombok.extern.slf4j.Slf4j;

/**
 * 2. 工作队列模式(Work Queues)消费者 - 消费者1
 * 多个消费者竞争消费消息,适用于任务分配和负载均衡。
 * 通过basicQos(1)实现消息确认机制,确保消息处理完成后再删除队列中的消息。
 * 
 * 架构:Producer -> Queue -> Consumer1, Consumer2, Consumer3(多个消费者竞争消费)
 * 观察三个接受者如何分配处理消息:HelloReceiver1、HelloReceiver2、HelloReceiver3,会均衡分配

@RabbitListener(queues = CloudConstant.MQ_JEECG_PLACE_ORDER) 注解声明一个消息队列,无的话项目在启动时回自动创建
@RabbitComponent(value = "helloReceiver1") 注解声明一个消费者
 * 
 * (@RabbitListener声明类上,一个类只能监听一个队列)
 * @author: zfq
 *
 */
@Slf4j
@RabbitListener(queues = CloudConstant.MQ_JEECG_PLACE_ORDER)
@RabbitComponent(value = "helloReceiver1")
public class HelloReceiver1 extends BaseRabbiMqHandler<BaseMap> {

    @Autowired
    private  RestTemplate restTemplate;

    @RabbitHandler
    public void onMessage(BaseMap baseMap, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        super.onMessage(baseMap, deliveryTag, channel, new MqListener<BaseMap>() {
            @Override
            public void handler(BaseMap map, Channel channel) {
                //业务处理
                String orderId = map.get("orderId").toString();
                log.info("【我是处理人1】 MQ Receiver1,orderId : " + orderId);
               // jeecgTestClient.getMessage("JEECG");
                try{
                    // 制造一个异常用于测试消息重新入队
                    if (orderId != null && orderId.startsWith("9")) {
                        // 当订单ID以9开头时,抛出异常,消息将重新入队
                        log.error("【测试异常】订单ID以9开头,抛出异常,消息将重新入队,orderId: {}", orderId);
                        throw new RuntimeException("模拟业务异常:订单ID以9开头,消息需要重新处理");
                    }
                    
                }catch (Exception e){
                    log.error("【消息处理异常】orderId: {}, 异常信息: {}", orderId, e.getMessage(), e);
                    // 重新抛出异常,让 BaseRabbiMqHandler 处理消息重新入队
                    throw new RuntimeException("消息处理失败,需要重新入队: " + e.getMessage(), e);
                }

            }
        });
    }

}

package org.jeecg.modules.test.rabbitmq.listener;//package org.jeecg.modules.cloud.rabbitmq;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.boot.starter.rabbitmq.core.BaseRabbiMqHandler;
import org.jeecg.boot.starter.rabbitmq.listenter.MqListener;
import org.jeecg.common.annotation.RabbitComponent;
import org.jeecg.common.base.BaseMap;
import org.jeecg.modules.test.rabbitmq.constant.CloudConstant;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;

/**
 * 2. 工作队列模式(Work Queues)消费者 - 消费者2
 * 多个消费者竞争消费消息,适用于任务分配和负载均衡。
 * 通过basicQos(1)实现消息确认机制,确保消息处理完成后再删除队列中的消息。
 * 
 * 架构:Producer -> Queue -> Consumer1, Consumer2, Consumer3(多个消费者竞争消费)
 * 观察三个接受者如何分配处理消息:HelloReceiver1、HelloReceiver2、HelloReceiver3,会均衡分配
 * 
 * (@RabbitListener声明类上,一个类只能监听一个队列)
 * @author: zyf
 * @date: 2022/04/21
 */
@Slf4j
@RabbitListener(queues = CloudConstant.MQ_JEECG_PLACE_ORDER)
@RabbitComponent(value = "helloReceiver2")
public class HelloReceiver2 extends BaseRabbiMqHandler<BaseMap> {

    @RabbitHandler
    public void onMessage(BaseMap baseMap, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        super.onMessage(baseMap, deliveryTag, channel, new MqListener<BaseMap>() {
            @Override
            public void handler(BaseMap map, Channel channel) {
                //业务处理
                String orderId = map.get("orderId").toString();
                log.info("【我是处理人2】 MQ Receiver2,orderId : " + orderId);
            }
        });
    }

}
相关推荐
独自破碎E3 小时前
怎么在RabbitMQ中配置消息的TTL?
分布式·rabbitmq
zhimingwen5 小时前
【開發筆記】修復 macOS 上 JADX 啟動崩潰並實現快速啟動
android·macos·反編譯
老臣软件5 小时前
桌面整洁又高效,Bartender让Mac焕然一新!
经验分享·macos·mac·实用软件
吃杠碰小鸡5 小时前
前端Mac快速搭建开发环境
前端·macos
Mi Manchi_345 小时前
Navicat 17 安装教程 mac
macos
魂之木6 小时前
【零基础教程】基于Docker的RabbitMQ部署方案
分布式·docker·微服务·rabbitmq
你好龙卷风!!!6 小时前
MQ相关的概念,ActiveMQ、RabbitMQ、Kafka、RocketMQ对比
rabbitmq
小镇学者6 小时前
【macos】warning: CRLF will be replaced by LF 问题解决方案
macos
TheNextByte17 小时前
如何将Mac上的联系人同步到 iPhone?
macos·cocoa·iphone