一.安装
-
**使用 Homebrew 安装(推荐)**:
- 打开终端,运行以下命令:
bashCopy Code
# 安装 RabbitMQ brew install rabbitmq # 启动 RabbitMQ 服务 brew services start rabbitmq -
配置环境变量:
- 将 RabbitMQ 的
sbin目录添加到 PATH:
bashCopy Code
echo 'export PATH="/usr/local/sbin:$PATH"' >> ~/.zshrc source ~/.zshrc - 将 RabbitMQ 的
-
访问管理界面:
- 启动后访问
http://localhost:15672 - 默认账号密码:
guest/guest
- 启动后访问
-
验证安装:
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;/**
-
- 简单模式(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("简单模式消息发送成功");
}
/**
-
- 工作队列模式(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("工作队列模式消息发送成功,观察多个消费者如何分配");
}
/**
-
- 发布/订阅模式(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("发布/订阅模式消息发送成功,所有订阅者都会收到");
}
/**
-
- 路由模式(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路由键)");
}
/**
-
- 主题模式(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)");
}
/**
-
- 远程过程调用(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);
}
});
}
}