rabbitmq的多交换机(扇出为例)监听实现

  1. 配置文件,微服务或者单体都可以在yml里配置,也可以写死在java文件.
yaml 复制代码
spring:
  rabbitmq:
    addresses: 127.0.0.1:5672
    username: guest
    password: guest
    virtual-host: /
    connection-timeout: 15000
    #配置rabbitMq启用开关
    enable: true
    listener:
      simple:
        acknowledge-mode: manual
        concurrency: 15
        max-concurrency: 20
  1. 监听处理文件
java 复制代码
package jzy.ziyuan.util.rabbitmq;

import cn.hutool.json.JSONObject;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import jnpf.util.JsonUtil;
import jzy.model.mom.EventMessageMom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

@Component
@ConditionalOnProperty(name = "spring.rabbitmq.enable", havingValue = "true", matchIfMissing = true)
public class MultiExchangeMessageListener {
    private static final Logger logger = LoggerFactory.getLogger(MultiExchangeMessageListener.class);

    @Autowired
    private IdempotentMessageProcessor idempotentProcessor;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 监听来自多个交换机的消息
     */

    // 声明 Direct 交换机、队列,并绑定路由键
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "order.queue", durable = "true"),    // 队列
            exchange = @Exchange(name = "20250917test1", type = ExchangeTypes.FANOUT) // 交换机
    ))
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "user.queue", durable = "true"),    
    @RabbitListener(queues = "#{tempQueue.name}") // 引用临时队列
    public void handleMessage(Message message) throws IOException {
        String messageId = message.getMessageProperties().getMessageId();
        String exchange = message.getMessageProperties().getReceivedExchange();
        long deliveryTag = message.getMessageProperties().getDeliveryTag();

        try {
            // 1. 幂等性检查
            if (idempotentProcessor.isProcessed(messageId)) {
                logger.info("消息已处理,跳过重复消费: messageId={}, exchange={}", messageId, exchange);
                // 手动确认消息
                rabbitTemplate.getConnectionFactory().createConnection().createChannel(false)
                        .basicAck(deliveryTag, false);
                return;
            }

            // 2. 处理消息内容
            String messageBody = new String(message.getBody(), "UTF-8");
            String processedMessage = replaceNbspWithSpace(messageBody);

            // 3. 解析消息
            JSONObject jsonObject = JsonUtil.getJsonToBean(processedMessage, JSONObject.class);
            EventMessageMom eventMessage = JsonUtil.getJsonToBean(jsonObject, EventMessageMom.class);

            logger.info("接收来自交换机的消息: exchange={}, messageId={}, content={}",
                    exchange, messageId, eventMessage);

            switch (exchange) {
                default:
                    break;
            }

            // 4. 执行业务逻辑


            // 5. 标记为已处理
            idempotentProcessor.markAsProcessed(messageId);

            // 6. 手动确认消息
            rabbitTemplate.getConnectionFactory().createConnection().createChannel(false)
                    .basicAck(deliveryTag, false);
            logger.info("消息处理成功: messageId={}, exchange={}", messageId, exchange);

        } catch (Exception e) {
            logger.error("消息处理失败: messageId={}, exchange={}", messageId, exchange, e);

            // 业务失败,拒绝消息并放入死信队列
            rabbitTemplate.getConnectionFactory().createConnection().createChannel(false)
                    .basicNack(deliveryTag, false, false); // 不重新入队
        }
    }

    /**
     * 过滤特殊符号
     */
    public static String replaceNbspWithSpace(String str) {
        if (str == null) {
            return null;
        }
        return str.replaceAll("\\u00A0", " ");
    }
}
  1. rabbitmq配置文件
java 复制代码
package jzy.ziyuan.util.rabbitmq;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class MultiExchangeRabbitConfig {

    // 交换机名称列表 - 可根据实际需求扩展
    public static final String[] EXCHANGE_NAMES = {
            "exchange.20250918logs",
            "exchange.20250918events",
            "exchange.20250918notifications"
    };

    // 交换机类型
    public static final String EXCHANGE_TYPE = "fanout";

    // 死信交换机和队列
    public static final String DLX_EXCHANGE = "20250918exchange.dlx";
    public static final String DLX_QUEUE = "20250918queue.dlx";

    /**
     * 创建死信交换机
     */
    @Bean
    public DirectExchange dlxExchange() {
        return ExchangeBuilder.directExchange(DLX_EXCHANGE)
                .durable(true)
                .build();
    }

    /**
     * 创建死信队列
     */
    @Bean
    public Queue dlxQueue() {
        return QueueBuilder.durable(DLX_QUEUE)
                .build();
    }

    /**
     * 绑定死信队列到死信交换机
     */
    @Bean
    public Binding dlxBinding() {
        return BindingBuilder.bind(dlxQueue())
                .to(dlxExchange())
                .with("dlx.routing.key");
    }

    /**
     * 创建临时队列 - 非持久化、排他、自动删除
     */
    @Bean
    public Queue tempQueue() {
        // 配置死信参数
        Map<String, Object> args = new HashMap<>();
        args.put("x-dead-letter-exchange", DLX_EXCHANGE);
        args.put("x-dead-letter-routing-key", "dlx.routing.key");

        return QueueBuilder.nonDurable()    // 非持久化
                .exclusive()                // 排他队列
                .autoDelete()               // 自动删除
                .withArguments(args)
                .build();
    }

    /**
     * 创建多个交换机并绑定到临时队列
     */
    @Bean
    public Declarables exchangeBindings() {
        Declarables declarables = new Declarables();

        // 创建所有交换机并绑定到临时队列
        for (String exchangeName : EXCHANGE_NAMES) {
            // 创建交换机
            FanoutExchange exchange = ExchangeBuilder.fanoutExchange(exchangeName)
                    .durable(true)
                    .build();
            declarables.getDeclarables().add(exchange);

            // 绑定交换机到临时队列
            Binding binding = BindingBuilder.bind(tempQueue())
                    .to(exchange);
            declarables.getDeclarables().add(binding);
        }

        return declarables;
    }

    /**
     * 配置监听容器工厂 - 手动ACK和QoS设置
     */
    @Bean
    public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL); // 手动确认
        factory.setPrefetchCount(10); // QoS设置
        factory.setConcurrentConsumers(3); // 并发消费者数量
        factory.setMaxConcurrentConsumers(5); // 最大并发消费者数量

        // 配置自动重连机制
        factory.setRecoveryInterval(5000L); // 重连间隔5秒

        return factory;
    }
}
相关推荐
用户8307196840821 天前
RabbitMQ vs RocketMQ 事务大对决:一个在“裸奔”,一个在“开挂”?
后端·rabbitmq·rocketmq
初次攀爬者2 天前
RabbitMQ的消息模式和高级特性
后端·消息队列·rabbitmq
初次攀爬者4 天前
ZooKeeper 实现分布式锁的两种方式
分布式·后端·zookeeper
让我上个超影吧5 天前
消息队列——RabbitMQ(高级)
java·rabbitmq
塔中妖5 天前
Windows 安装 RabbitMQ 详细教程(含 Erlang 环境配置)
windows·rabbitmq·erlang
断手当码农5 天前
Redis 实现分布式锁的三种方式
数据库·redis·分布式
初次攀爬者5 天前
Redis分布式锁实现的三种方式-基于setnx,lua脚本和Redisson
redis·分布式·后端
业精于勤_荒于稀5 天前
物流订单系统99.99%可用性全链路容灾体系落地操作手册
分布式
Ronin3055 天前
信道管理模块和异步线程模块
开发语言·c++·rabbitmq·异步线程·信道管理
Asher05095 天前
Hadoop核心技术与实战指南
大数据·hadoop·分布式