Spring AMQP 最佳实践指南

目录

  1. [Spring AMQP 概述](#Spring AMQP 概述)

  2. 快速集成

    • 2.1 [Maven 依赖](#Maven 依赖)

    • 2.2 [Gradle 依赖](#Gradle 依赖)

    • 2.3 [Spring Boot 自动配置](#Spring Boot 自动配置)

    • 2.4 [纯 Java 配置](#纯 Java 配置)

    • 2.5 [XML 配置](#XML 配置)

  3. 核心概念

    • 3.1 [AMQP 抽象(Exchange / Queue / Binding / Message)](#AMQP 抽象(Exchange / Queue / Binding / Message))

    • 3.2 连接与资源管理

    • 3.3 [AmqpTemplate / RabbitTemplate](#AmqpTemplate / RabbitTemplate)

  4. 消息发送

  5. 消息接收

  6. 消息转换器

  7. [请求 / 回复模式](#请求 / 回复模式)

  8. [Broker 配置](#Broker 配置)

  9. 异常处理与重试

  10. 事务支持

  11. 监听器容器配置

  12. 容错与恢复(Resilience)

  13. 测试支持

  14. [完整 Demo 示例](#完整 Demo 示例)

  15. 组件开发示例

  16. 最佳实践清单


1. Spring AMQP 概述

Spring AMQP 是一个基于 AMQP(Advanced Message Queuing Protocol) 协议的消息中间件框架,提供简洁的 API 来发送和接收异步、可靠的消息。它是 Spring 生态的一部分,与 Spring Boot、Spring Integration 等项目无缝集成。

核心能力:

  • AmqpTemplate / RabbitTemplate:高层抽象,简化消息的发送与接收

  • @RabbitListener:注解驱动的消息驱动 POJO

  • 消息转换器:自动进行 Java 对象与 AMQP 消息体之间的序列化/反序列化

  • 连接管理:连接与 Channel 的缓存、自动恢复

  • 声明式配置:Exchange、Queue、Binding 的自动声明

  • 消息确认、事务、重试:可靠性保障机制

  • Micrometer 可观测性:指标与链路追踪

版本兼容性(3.0.x):

  • Java 17+

  • Spring Framework 6.0+

  • RabbitMQ amqp-client 5.7.0+


2. 快速集成

2.1 Maven 依赖

复制代码
<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-rabbit</artifactId>
    <version>3.0.4</version>
</dependency>

2.2 Gradle 依赖

复制代码
implementation 'org.springframework.amqp:spring-rabbit:3.0.4'

2.3 Spring Boot 自动配置(推荐)

Spring Boot 自动配置 ConnectionFactoryRabbitTemplateRabbitAdmin 等基础设施 Bean。

application.yml:

复制代码
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    # 发布者确认
    publisher-confirm-type: correlated
    publisher-returns: true
    # 消费者
    listener:
      simple:
        concurrency: 3
        max-concurrency: 10
        acknowledge-mode: manual
        retry:
          enabled: true
          max-attempts: 3
          initial-interval: 1000ms

示例应用:

复制代码
@SpringBootApplication
public class Application {
​
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
​
    @Bean
    public Queue myQueue() {
        return new Queue("myqueue");
    }
​
    @Bean
    public ApplicationRunner runner(RabbitTemplate template) {
        return args -> template.convertAndSend("myqueue", "Hello, World!");
    }
​
    @RabbitListener(queues = "myqueue")
    public void listen(String message) {
        System.out.println("Received: " + message);
    }
}

2.4 纯 Java 配置

复制代码
@Configuration
public class RabbitConfiguration {
​
    @Bean
    public CachingConnectionFactory connectionFactory() {
        CachingConnectionFactory factory = new CachingConnectionFactory("localhost");
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");
        // 启用发布者确认
        factory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
        factory.setPublisherReturns(true);
        return factory;
    }
​
    @Bean
    public RabbitAdmin amqpAdmin(ConnectionFactory connectionFactory) {
        return new RabbitAdmin(connectionFactory);
    }
​
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        // 设置消息转换器
        template.setMessageConverter(jackson2MessageConverter());
        // 确认回调
        template.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                System.out.println("消息发送成功: " + correlationData);
            } else {
                System.err.println("消息发送失败: " + cause);
            }
        });
        // 返回回调
        template.setReturnsCallback(returned -> {
            System.err.println("消息被退回: " + returned.getMessage());
        });
        return template;
    }
​
    @Bean
    public Jackson2JsonMessageConverter jackson2MessageConverter() {
        return new Jackson2JsonMessageConverter();
    }
​
    @Bean
    public Queue myQueue() {
        return new Queue("myqueue", true); // 持久化队列
    }
}

2.5 XML 配置

复制代码
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xsi:schemaLocation="
         http://www.springframework.org/schema/rabbit
         https://www.springframework.org/schema/rabbit/spring-rabbit.xsd
         http://www.springframework.org/schema/beans
         https://www.springframework.org/schema/beans/spring-beans.xsd">
​
    <rabbit:connection-factory id="connectionFactory" host="localhost"/>
​
    <rabbit:template id="amqpTemplate"
                     connection-factory="connectionFactory"/>
​
    <rabbit:admin connection-factory="connectionFactory"/>
​
    <rabbit:queue name="myqueue"/>
​
</beans>

3. 核心概念

3.1 AMQP 抽象

AMQP 协议的三大核心要素:

概念 说明 关键类
Exchange 消息交换机,接收生产者消息并按路由规则分发到队列 DirectExchange, TopicExchange, FanoutExchange, HeadersExchange
Queue 消息队列,存储消息直到被消费者取走 Queue, AnonymousQueue
Binding 绑定关系,定义 Exchange 到 Queue 的路由规则(routing key) Binding
Message 消息体,包含 body(字节数组)和 properties(消息属性) Message

Exchange 类型:

复制代码
// Direct Exchange:精确匹配 routing key
new DirectExchange("order.exchange");
​
// Topic Exchange:通配符匹配 routing key(* 匹配一个词,# 匹配零个或多个词)
new TopicExchange("event.exchange");
​
// Fanout Exchange:广播到所有绑定队列,忽略 routing key
new FanoutExchange("broadcast.exchange");
​
// Headers Exchange:根据消息 headers 匹配
new HeadersExchange("header.exchange");

声明示例:

复制代码
@Bean
public DirectExchange orderExchange() {
    return new DirectExchange("order.exchange", true, false);
}
​
@Bean
public Queue orderQueue() {
    return QueueBuilder.durable("order.queue")
            .withArgument("x-dead-letter-exchange", "dlx.exchange")
            .withArgument("x-dead-letter-routing-key", "dlx.routing.key")
            .build();
}
​
@Bean
public Binding orderBinding(DirectExchange orderExchange, Queue orderQueue) {
    return BindingBuilder.bind(orderQueue)
            .to(orderExchange)
            .with("order.created");
}

3.2 连接与资源管理

CachingConnectionFactory(核心连接工厂)
复制代码
@Bean
public CachingConnectionFactory connectionFactory() {
    CachingConnectionFactory factory = new CachingConnectionFactory("localhost");
    factory.setUsername("guest");
    factory.setPassword("guest");
    factory.setVirtualHost("/");
    factory.setPort(5672);
​
    // Channel 缓存大小(默认 25)
    factory.setChannelCacheSize(50);
​
    // 连接缓存模式:CHANNEL(默认)/ CONNECTION
    factory.setCacheMode(CachingConnectionFactory.CacheMode.CHANNEL);
​
    // 连接限制
    factory.setChannelCheckoutTimeout(1000); // Channel 获取超时(ms)
​
    // 发布者确认
    factory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
    factory.setPublisherReturns(true);
​
    return factory;
}
SSL 配置
复制代码
@Bean
public RabbitConnectionFactoryBean rabbitConnectionFactory() {
    RabbitConnectionFactoryBean factory = new RabbitConnectionFactoryBean();
    factory.setUseSSL(true);
    factory.setSslAlgorithm("TLSv1.2");
    factory.setKeyStore("file:/path/to/keystore.jks");
    factory.setKeyStorePassphrase("password");
    factory.setTrustStore("file:/path/to/truststore.jks");
    factory.setTrustStorePassphrase("password");
    return factory;
}
​
@Bean
public CachingConnectionFactory connectionFactory(
        RabbitConnectionFactoryBean rabbitConnectionFactory) throws Exception {
    return new CachingConnectionFactory(rabbitConnectionFactory.getObject());
}
集群连接
复制代码
// addresses 格式:host1:port1,host2:port2
@Bean
public CachingConnectionFactory connectionFactory() {
    CachingConnectionFactory factory = new CachingConnectionFactory();
    factory.setAddresses("rabbit1:5672,rabbit2:5672,rabbit3:5672");
    factory.setUsername("guest");
    factory.setPassword("guest");
    return factory;
}
​
// 使用 AddressResolver 动态发现
@Bean
public CachingConnectionFactory connectionFactory(AddressResolver addressResolver) {
    CachingConnectionFactory factory = new CachingConnectionFactory();
    factory.setAddressResolver(addressResolver);
    return factory;
}
RabbitMQ 自动连接/拓扑恢复
复制代码
spring:
  rabbitmq:
    connection-timeout: 30000
    requested-heartbeat: 60s
    # 自动恢复(RabbitMQ 客户端 4.0+ 默认启用)
    # 以下参数可覆写默认恢复行为

3.3 AmqpTemplate / RabbitTemplate

RabbitTemplateAmqpTemplate 接口的核心实现,提供同步和异步消息操作。

添加重试能力
复制代码
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
    RabbitTemplate template = new RabbitTemplate(connectionFactory);
​
    // 配置重试模板
    RetryTemplate retryTemplate = RetryTemplate.builder()
            .maxAttempts(3)
            .fixedBackoff(1000) // 固定间隔 1s
            .retryOn(AmqpIOException.class)
            .build();
    template.setRetryTemplate(retryTemplate);
​
    return template;
}
异步发布 --- 检测成功与失败
复制代码
// 确认回调
template.setConfirmCallback((correlationData, ack, cause) -> {
    if (ack) {
        log.info("消息 {} 已确认", correlationData.getId());
    } else {
        log.error("消息 {} 发送失败: {}", correlationData.getId(), cause);
        // 可在此做补偿逻辑:重发、记录到数据库
    }
});
​
// 退回回调(消息无法路由到队列时触发)
template.setReturnsCallback(returned -> {
    Message message = returned.getMessage();
    String replyText = returned.getReplyText();
    String exchange = returned.getExchange();
    String routingKey = returned.getRoutingKey();
    log.error("消息被退回: replyText={}, exchange={}, routingKey={}",
            replyText, exchange, routingKey);
});
Scope 操作(声明式交换/队列绑定后发送)
复制代码
// 使用 invoke 方法,在发送消息前确保交换和队列已声明
template.invoke(t -> {
    // 在此声明
    t.execute(channel -> {
        channel.exchangeDeclare("temp.exchange", "direct", true);
        channel.queueDeclare("temp.queue", true, false, false, null);
        channel.queueBind("temp.queue", "temp.exchange", "routing.key");
        return null;
    });
    // 然后发送
    t.convertAndSend("temp.exchange", "routing.key", payload);
    return null;
});

4. 消息发送

Message Builder API

复制代码
// 方式一:MessageBuilder
Message message = MessageBuilder.withBody("Hello".getBytes())
        .setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN)
        .setMessageId(UUID.randomUUID().toString())
        .setHeader("custom-header", "custom-value")
        .setPriority(5)
        .setDeliveryMode(MessageDeliveryMode.PERSISTENT)
        .build();
template.send("my.exchange", "my.routing.key", message);
​
// 方式二:MessagePostProcessor
template.convertAndSend("my.exchange", "my.routing.key", payload, msg -> {
    msg.getMessageProperties().setHeader("trace-id", traceId());
    msg.getMessageProperties().setExpiration("60000"); // 60s TTL
    return msg;
});

批处理

复制代码
// 发送批量消息
List<Message> messages = Arrays.asList(
    MessageBuilder.withBody("batch-1".getBytes()).build(),
    MessageBuilder.withBody("batch-2".getBytes()).build(),
    MessageBuilder.withBody("batch-3".getBytes()).build()
);
​
// BatchingStrategy 控制批次大小和缓冲时间
BatchingRabbitTemplate batchingTemplate = new BatchingRabbitTemplate(
        connectionFactory,
        new SimpleBatchingStrategy(100, 1024 * 1024, 5000) // 100条/1MB/5s
);
batchingTemplate.send("my.exchange", "my.routing.key", messages);

5. 消息接收

消费者轮询(Polling Consumer)

复制代码
// 同步接收
Message msg = template.receive("my.queue", 3000); // 3s 超时
String body = (String) template.receiveAndConvert("my.queue", 3000);
​
// 支持超时和类型转换
Order order = (Order) template.receiveAndConvert("order.queue", 5000);

异步消费者 --- @RabbitListener

复制代码
@Component
public class OrderListener {
​
    @RabbitListener(queues = "order.queue")
    public void handleOrder(Order order) {
        log.info("收到订单: {}", order);
        processOrder(order);
    }
​
    // 手动确认模式
    @RabbitListener(queues = "order.queue", ackMode = "MANUAL")
    public void handleOrderManual(Order order, Channel channel,
                                  @Header(AmqpHeaders.DELIVERY_TAG) long tag) {
        try {
            processOrder(order);
            channel.basicAck(tag, false);
        } catch (Exception e) {
            channel.basicNack(tag, false, true); // requeue
        }
    }
​
    // 监听多个队列
    @RabbitListener(queues = {"order.created", "order.updated", "order.cancelled"})
    public void handleOrderEvents(OrderEvent event,
                                  @Header("event-type") String eventType) {
        log.info("事件 [{}]: {}", eventType, event);
    }
​
    // 批处理监听
    @RabbitListener(queues = "order.batch.queue", containerFactory = "batchContainerFactory")
    public void handleBatch(List<Order> orders) {
        log.info("批量处理 {} 条订单", orders.size());
        orders.forEach(this::processOrder);
    }
​
    // 异步返回
    @RabbitListener(queues = "rpc.queue")
    @SendTo("reply.queue") // 将返回值发送到 reply.queue
    public String handleRpc(String request) {
        return "Response for: " + request;
    }
}

容器工厂配置

复制代码
@Configuration
public class ListenerConfig {
​
    // 常规容器工厂
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
            ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setConcurrentConsumers(3);          // 初始并发消费者
        factory.setMaxConcurrentConsumers(10);       // 最大并发消费者
        factory.setPrefetchCount(50);                // 预取数量
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        factory.setDefaultRequeueRejected(false);    // 拒绝时不重新入队
        factory.setMessageConverter(jackson2MessageConverter());
        return factory;
    }
​
    // 批处理容器工厂
    @Bean
    public SimpleRabbitListenerContainerFactory batchContainerFactory(
            ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setBatchListener(true);             // 启用批处理
        factory.setBatchSize(50);                    // 批次大小
        factory.setConsumerBatchEnabled(true);       // 消费者端批次
        factory.setReceiveTimeout(5000L);            // 批次超时
        return factory;
    }
​
    @Bean
    public Jackson2JsonMessageConverter jackson2MessageConverter() {
        return new Jackson2JsonMessageConverter();
    }
}

两种容器对比

特性 SimpleMessageListenerContainer DirectMessageListenerContainer
并发模型 多线程,每个消费者一个线程 每个队列一个 Channel,单线程
适用场景 事务、大量队列、需严格排序 高吞吐、少量队列、低延迟
预取控制 支持 prefetchCount 支持 prefetchCount
事务支持
动态扩缩
使用方式 默认容器 需显式指定 containerFactory

6. 消息转换器

常用转换器一览

复制代码
// 1. SimpleMessageConverter — 默认,处理 String、byte[]、Serializable
template.setMessageConverter(new SimpleMessageConverter());
​
// 2. Jackson2JsonMessageConverter — JSON 序列化(推荐)
Jackson2JsonMessageConverter jsonConverter = new Jackson2JsonMessageConverter();
// 支持类型安全反序列化
jsonConverter.setClassMapper(new DefaultJackson2JavaTypeMapper());
template.setMessageConverter(jsonConverter);
​
// 3. Jackson2XmlMessageConverter — XML 序列化
template.setMessageConverter(new Jackson2XmlMessageConverter());
​
// 4. MarshallingMessageConverter — 基于 Spring OXM
template.setMessageConverter(new MarshallingMessageConverter(jaxb2Marshaller()));
​
// 5. ContentTypeDelegatingMessageConverter — 根据 Content-Type 委托
ContentTypeDelegatingMessageConverter delegating = new ContentTypeDelegatingMessageConverter();
delegating.addDelegate("application/json", jsonConverter);
delegating.addDelegate("application/xml", xmlConverter);
delegating.addDelegate("text/plain", simpleConverter);
template.setMessageConverter(delegating);

类型安全的 JSON 转换

复制代码
@RabbitListener(queues = "order.queue")
public void handleOrder(
        @Payload Order order,
        @Header(AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey) {
    // @Payload 配合 DefaultJackson2JavaTypeMapper 确保类型正确
}
​
// 自定义 ClassMapper:通过消息头指定类型
DefaultJackson2JavaTypeMapper typeMapper = new DefaultJackson2JavaTypeMapper();
typeMapper.setTypePrecedence(Jackson2JavaTypeMapper.TypePrecedence.TYPE_ID);
// 消息发送时自动设置 __TypeId__ header

消息属性转换器

复制代码
// 自定义 MessagePropertiesConverter
// 可自定义 AMQP 消息属性与 Spring MessageProperties 的映射

7. 请求 / 回复模式

同步请求 / 回复

复制代码
// 发送并等待回复
Object response = template.convertSendAndReceive(
        "rpc.exchange", "rpc.key", request);
// 默认超时 5s,可配置
template.setReplyTimeout(30000);

异步请求 / 回复 --- AsyncRabbitTemplate

复制代码
@Configuration
public class AsyncConfig {
​
    @Bean
    public AsyncRabbitTemplate asyncRabbitTemplate(
            ConnectionFactory connectionFactory) {
        // 方式一:使用固定回复队列
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        Queue replyQueue = new Queue("async.reply.queue");
        AsyncRabbitTemplate asyncTemplate = new AsyncRabbitTemplate(
                rabbitTemplate, new SimpleMessageListenerContainer(connectionFactory), replyQueue.getName());
        return asyncTemplate;
    }
}
​
// 使用
@Component
public class RpcClient {
​
    @Autowired
    private AsyncRabbitTemplate asyncTemplate;
​
    public CompletableFuture<String> callAsync(String request) {
        RabbitConverterFuture<String> future = asyncTemplate.convertSendAndReceiveAsType(
                "rpc.exchange", "rpc.key", request,
                new ParameterizedTypeReference<String>() {});
        return future.completable(); // 转换为 CompletableFuture
    }
}

服务端 --- @RabbitListener + @SendTo

复制代码
@RabbitListener(queues = "rpc.queue")
@SendTo("reply.to.queue")  // 自动将返回值发送到指定队列
public OrderResult processOrder(OrderRequest request) {
    return orderService.process(request);
}

RabbitMQ Direct Reply-to(零队列优化)

复制代码
// 启用 Direct Reply-to,无需声明回复队列,性能更优
template.setUseDirectReplyToContainer(true);
template.setReplyAddress("amq.rabbitmq.reply-to"); // 伪队列名

8. Broker 配置

Builder API 声明

复制代码
@Configuration
public class BrokerConfig {
​
    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
        RabbitAdmin admin = new RabbitAdmin(connectionFactory);
        admin.setAutoStartup(true); // 自动声明
        return admin;
    }
​
    // Exchange Builder
    @Bean
    public DirectExchange orderExchange() {
        return ExchangeBuilder.directExchange("order.exchange")
                .durable(true)
                .autoDelete(false)
                .delayed()
                .build();
    }
​
    // Queue Builder(带死信配置)
    @Bean
    public Queue orderQueue() {
        return QueueBuilder.durable("order.queue")
                .withArgument("x-dead-letter-exchange", "dlx.exchange")
                .withArgument("x-dead-letter-routing-key", "order.dead")
                .withArgument("x-message-ttl", 60000)        // 消息 TTL
                .withArgument("x-max-length", 10000)          // 最大长度
                .maxPriority(10)                               // 最大优先级
                .quorum()                                      // 仲裁队列
                .build();
    }
​
    // Binding Builder
    @Bean
    public Binding orderBinding() {
        return BindingBuilder.bind(orderQueue())
                .to(orderExchange())
                .with("order.created");
    }
​
    // 延迟队列插件(需要安装 rabbitmq_delayed_message_exchange)
    @Bean
    public DirectExchange delayedExchange() {
        return ExchangeBuilder.directExchange("delayed.exchange")
                .delayed()
                .build();
    }
​
    // 发送延迟消息
    public void sendDelayed(Object payload, int delayMs) {
        template.convertAndSend("delayed.exchange", "delayed.key", payload, msg -> {
            msg.getMessageProperties().setDelay(delayMs);
            return msg;
        });
    }
​
    // AnonymousQueue(自动生成名称,连接断开自动删除)
    @Bean
    public Queue anonymousQueue() {
        return new AnonymousQueue();
    }
​
    // 条件声明
    @Bean
    public Declarables declarables() {
        return new Declarables(
            new DirectExchange("conditional.exchange"),
            new Queue("conditional.queue"),
            new Binding("conditional.queue", Binding.DestinationType.QUEUE,
                    "conditional.exchange", "routing.key", null)
        );
    }
}

Broker 事件监听器

复制代码
@Component
public class BrokerEventListener implements ApplicationListener<BrokerEvent> {
​
    @Override
    public void onApplicationEvent(BrokerEvent event) {
        if (event instanceof BrokerAvailableEvent) {
            log.info("Broker 已可用");
        } else if (event instanceof BrokerUnavailableEvent) {
            log.warn("Broker 不可用");
        }
    }
​
    // 或通过 @EventListener
    @EventListener
    public void handleBrokerAvailable(BrokerAvailableEvent event) {
        log.info("Broker 可用");
    }
}

9. 异常处理与重试

重试策略配置

复制代码
// 监听器级别重试
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
        ConnectionFactory connectionFactory) {
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
​
    // 使用 RetryTemplate
    RetryTemplate retryTemplate = RetryTemplate.builder()
            .maxAttempts(3)
            .exponentialBackoff(1000, 2.0, 10000)  // 指数退避
            .retryOn(AmqpRejectAndDontRequeueException.class) // 不重试的异常
            .build();
    factory.setRetryTemplate(retryTemplate);
​
    return factory;
}

死信队列与 RepublishMessageRecoverer

复制代码
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
        ConnectionFactory connectionFactory) {
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
​
    // 重试耗尽后将消息重新发布到死信队列
    MessageRecoverer recoverer = new RepublishMessageRecoverer(
            rabbitTemplate(connectionFactory), "dlx.exchange", "dlx.routing.key");
    RetryTemplate retryTemplate = RetryTemplate.builder()
            .maxAttempts(3)
            .exponentialBackoff(1000, 2.0, 10000)
            .build();
    factory.setRetryTemplate(retryTemplate);
    factory.setRecoveryCallback(new RetryContextExhaustedMessageRecoverer(recoverer));
​
    return factory;
}

@RabbitListener 异常处理

复制代码
@Component
public class ExceptionHandlingListener {
​
    @RabbitListener(queues = "order.queue")
    public void handleOrder(Order order) {
        try {
            processOrder(order);
        } catch (OrderValidationException e) {
            // 业务异常,不重试,直接拒绝
            throw new AmqpRejectAndDontRequeueException("订单校验失败", e);
        } catch (TemporaryException e) {
            // 临时异常,重试
            throw e;
        }
    }
​
    // 全局异常处理器
    @RabbitListener(queues = "order.queue", errorHandler = "myErrorHandler")
    public void handleWithErrorHandler(Order order) {
        processOrder(order);
    }
}
​
// 自定义 ErrorHandler
@Component("myErrorHandler")
public class CustomErrorHandler implements RabbitListenerErrorHandler {
​
    @Override
    public Object handleError(Message amqpMessage, org.springframework.messaging.Message<?> message,
                              ListenerExecutionFailedException exception) {
        log.error("消息处理失败: {}", new String(amqpMessage.getBody()), exception);
        // 返回 null 表示消费成功(丢弃消息)
        return null;
    }
}

10. 事务支持

复制代码
// 1. 启用 RabbitTemplate 事务
template.setChannelTransacted(true);
​
// 2. 使用 RabbitTransactionManager
@Bean
public RabbitTransactionManager transactionManager(
        ConnectionFactory connectionFactory) {
    return new RabbitTransactionManager(connectionFactory);
}
​
// 3. @Transactional 声明式事务
@Transactional(transactionManager = "rabbitTransactionManager")
public void sendWithTransaction() {
    template.convertAndSend("exchange", "queue1", "message1");
    template.convertAndSend("exchange", "queue2", "message2");
    // 如果任一发送失败,两者都回滚
}
​
// 4. 监听器容器事务
@Bean
public SimpleRabbitListenerContainerFactory transactionalContainerFactory(
        ConnectionFactory connectionFactory,
        RabbitTransactionManager transactionManager) {
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    factory.setChannelTransacted(true);
    factory.setTransactionManager(transactionManager);
    return factory;
}
​
// 5. 条件回滚
@Transactional(transactionManager = "rabbitTransactionManager")
public void conditionalRollback() {
    template.convertAndSend("exchange", "queueA", "msgA");
    // 基于条件决定是否回滚
    if (shouldRollback()) {
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}

11. 监听器容器配置

SimpleMessageListenerContainer 直接编程式

复制代码
@Bean
public SimpleMessageListenerContainer messageListenerContainer(
        ConnectionFactory connectionFactory,
        MessageListenerAdapter listenerAdapter) {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(connectionFactory);
    container.setQueueNames("order.queue", "event.queue");
    container.setMessageListener(listenerAdapter);
    container.setConcurrentConsumers(5);
    container.setMaxConcurrentConsumers(20);
    container.setPrefetchCount(100);
    container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    container.setAutoStartup(true);
    return container;
}
​
// MessageListenerAdapter 适配 POJO
@Bean
public MessageListenerAdapter listenerAdapter(OrderProcessor processor) {
    MessageListenerAdapter adapter = new MessageListenerAdapter(processor);
    adapter.setDefaultListenerMethod("process");
    adapter.setMessageConverter(jackson2MessageConverter());
    return adapter;
}

DirectMessageListenerContainer

复制代码
@Bean
public DirectRabbitListenerContainerFactory directContainerFactory(
        ConnectionFactory connectionFactory) {
    DirectRabbitListenerContainerFactory factory = new DirectRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    factory.setConsumersPerQueue(5);       // 每个队列的消费者数
    factory.setPrefetchCount(100);
    return factory;
}
​
// 使用时指定
@RabbitListener(queues = "high.throughput.queue",
        containerFactory = "directContainerFactory")
public void handleHighThroughput(Message msg) {
    // 高吞吐场景
}

12. 容错与恢复(Resilience)

自动恢复机制

Spring AMQP 内置了从 Broker 故障中恢复的能力:

复制代码
@Bean
public CachingConnectionFactory connectionFactory() {
    CachingConnectionFactory factory = new CachingConnectionFactory("localhost");
    // 连接恢复间隔
    factory.setRecoveryInterval(5000);
    return factory;
}

RabbitAdmin 自动声明

复制代码
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
    RabbitAdmin admin = new RabbitAdmin(connectionFactory);
    // Broker 恢复连接后自动重新声明 Exchange/Queue/Binding
    admin.setAutoStartup(true);
    return admin;
}

同步操作失败重试

复制代码
// RabbitTemplate 层面自动重试
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
    RabbitTemplate template = new RabbitTemplate(connectionFactory);
    RetryTemplate retryTemplate = RetryTemplate.builder()
            .maxAttempts(5)
            .exponentialBackoff(500, 2.0, 5000)
            .retryOn(AmqpConnectException.class)
            .build();
    template.setRetryTemplate(retryTemplate);
    return template;
}

异常分类

复制代码
// 致命异常 — 不应重试
AmqpRejectAndDontRequeueException     // 拒绝且不重新入队
ImmediateAcknowledgeAmqpException      // 立即确认(丢弃)
MessageConversionException             // 消息转换失败
​
// 可重试异常 — 建议重试
AmqpConnectException                   // 连接异常
AmqpIOException                        // IO 异常
ListenerExecutionFailedException       // 监听器执行失败

13. 测试支持

@SpringRabbitTest

复制代码
@SpringRabbitTest
@SpringBootTest
class OrderListenerTest {
​
    @Autowired
    private RabbitTemplate rabbitTemplate;
​
    @Autowired
    private RabbitListenerTestHarness harness;
​
    @Test
    void testOrderProcessing() throws InterruptedException {
        // 发送测试消息
        rabbitTemplate.convertAndSend("order.exchange", "order.created",
                new Order("test-order", 100));
​
        // 获取监听器 spy
        OrderListener listener = harness.getSpy("orderListener");
        // 验证
        verify(listener, timeout(5000)).handleOrder(any(Order.class));
    }
}

@RabbitListenerTest 与 RabbitListenerTestHarness

复制代码
@SpringBootTest
class ListenerTest {
​
    @Autowired
    private RabbitListenerTestHarness harness;
​
    @Test
    void testCapture() {
        RabbitListenerTestHarness.InvocationData invocationData =
                harness.getNextInvocationDataFor("myListener", 10, TimeUnit.SECONDS);
​
        assertNotNull(invocationData);
        assertEquals("expected-payload", invocationData.getArguments()[0]);
    }
}

TestRabbitTemplate

复制代码
@Test
void testWithTestTemplate() {
    TestRabbitTemplate template = new TestRabbitTemplate(connectionFactory);
    template.convertAndSend("order.exchange", "order.created", testOrder);
    // 等待处理并通过模板验证状态
}

JUnit5 条件

复制代码
@RabbitAvailable  // Broker 可用时才执行
@SpringBootTest
class IntegrationTest {
​
    @Test
    void testWithBroker() {
        // 仅在 RabbitMQ 可用时运行
    }
}
​
@LongRunning  // 长时测试标记
@SpringBootTest
class LongRunningTest {
​
    @Test
    void testLongRunning() {
        // 可能耗时的集成测试
    }
}

14. 完整 Demo 示例

14.1 Hello World --- 同步版

复制代码
public class HelloWorldSync {
    public static void main(String[] args) {
        ConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
        AmqpAdmin admin = new RabbitAdmin(connectionFactory);
        admin.declareQueue(new Queue("myqueue"));
​
        AmqpTemplate template = new RabbitTemplate(connectionFactory);
        template.convertAndSend("myqueue", "foo");
​
        String result = (String) template.receiveAndConvert("myqueue");
        System.out.println("Received: " + result); // Received: foo
    }
}

14.2 Hello World --- 异步版(Spring Boot)

复制代码
@SpringBootApplication
public class HelloWorldAsync {
​
    public static void main(String[] args) {
        SpringApplication.run(HelloWorldAsync.class, args);
    }
​
    // --- 生产者 ---
    @Bean
    public Queue helloQueue() {
        return new Queue("hello.queue");
    }
​
    @Bean
    public ApplicationRunner producer(RabbitTemplate template) {
        return args -> {
            for (int i = 0; i < 10; i++) {
                template.convertAndSend("hello.queue", "Message #" + i);
            }
            System.out.println("10 messages sent.");
        };
    }
​
    // --- 消费者 ---
    @RabbitListener(queues = "hello.queue")
    public void consumer(String message) {
        System.out.println("Received: " + message);
    }
}

14.3 订单处理系统(完整示例)

项目结构:

复制代码
com.example.order
├── config
│   └── RabbitConfig.java
├── model
│   ├── Order.java
│   └── OrderResult.java
├── service
│   ├── OrderService.java
│   └── NotificationService.java
├── listener
│   └── OrderListener.java
├── controller
│   └── OrderController.java
└── OrderApplication.java

配置类:

复制代码
@Configuration
public class RabbitConfig {
​
    // ============ Connection ============
    @Bean
    public CachingConnectionFactory connectionFactory() {
        CachingConnectionFactory factory = new CachingConnectionFactory("localhost");
        factory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
        factory.setPublisherReturns(true);
        return factory;
    }
​
    // ============ Exchanges ============
    @Bean
    public TopicExchange orderExchange() {
        return ExchangeBuilder.topicExchange("order.exchange").durable(true).build();
    }
​
    @Bean
    public DirectExchange dlxExchange() {
        return new DirectExchange("order.dlx.exchange");
    }
​
    // ============ Queues ============
    @Bean
    public Queue orderCreateQueue() {
        return QueueBuilder.durable("order.create.queue")
                .withArgument("x-dead-letter-exchange", "order.dlx.exchange")
                .withArgument("x-dead-letter-routing-key", "order.dead")
                .build();
    }
​
    @Bean
    public Queue orderDeadQueue() {
        return QueueBuilder.durable("order.dead.queue").build();
    }
​
    @Bean
    public Queue notificationQueue() {
        return QueueBuilder.durable("order.notification.queue")
                .withArgument("x-dead-letter-exchange", "order.dlx.exchange")
                .withArgument("x-dead-letter-routing-key", "order.dead")
                .build();
    }
​
    // ============ Bindings ============
    @Bean
    public Binding createBinding() {
        return BindingBuilder.bind(orderCreateQueue())
                .to(orderExchange()).with("order.created");
    }
​
    @Bean
    public Binding deadBinding() {
        return BindingBuilder.bind(orderDeadQueue())
                .to(dlxExchange()).with("order.dead");
    }
​
    @Bean
    public Binding notificationBinding() {
        return BindingBuilder.bind(notificationQueue())
                .to(orderExchange()).with("order.*");
    }
​
    // ============ RabbitTemplate ============
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(jackson2MessageConverter());
​
        template.setConfirmCallback((correlationData, ack, cause) -> {
            String id = correlationData != null ? correlationData.getId() : "unknown";
            if (ack) {
                log.info("订单消息确认: {}", id);
            } else {
                log.error("订单消息发送失败: {}, 原因: {}", id, cause);
            }
        });
​
        template.setReturnsCallback(returned ->
                log.error("订单消息退回到 {}:{} — {}",
                        returned.getExchange(), returned.getRoutingKey(),
                        new String(returned.getMessage().getBody()))
        );
​
        return template;
    }
​
    // ============ Listener Container ============
    @Bean
    public SimpleRabbitListenerContainerFactory orderListenerFactory(
            ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setConcurrentConsumers(5);
        factory.setMaxConcurrentConsumers(20);
        factory.setPrefetchCount(50);
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        factory.setMessageConverter(jackson2MessageConverter());
​
        // 重试策略
        RetryTemplate retryTemplate = RetryTemplate.builder()
                .maxAttempts(3)
                .exponentialBackoff(1000, 2.0, 5000)
                .build();
​
        // 重试耗尽后发送到死信队列
        MessageRecoverer recoverer = new RepublishMessageRecoverer(
                rabbitTemplate(connectionFactory), "order.dlx.exchange", "order.dead");
        factory.setRetryTemplate(retryTemplate);
        factory.setRecoveryCallback(new RetryContextExhaustedMessageRecoverer(recoverer));
​
        return factory;
    }
​
    @Bean
    public Jackson2JsonMessageConverter jackson2MessageConverter() {
        Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
        // 信任所有包(生产环境应限制)
        converter.setClassMapper(new DefaultJackson2JavaTypeMapper());
        return converter;
    }
​
    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
        return new RabbitAdmin(connectionFactory);
    }
}

监听器:

复制代码
@Component
@Slf4j
public class OrderListener {
​
    @Autowired
    private OrderService orderService;
    @Autowired
    private NotificationService notificationService;
​
    @RabbitListener(queues = "order.create.queue",
            containerFactory = "orderListenerFactory")
    public void handleOrderCreated(
            Order order,
            Channel channel,
            @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
            @Header(AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey)
            throws IOException {
​
        log.info("收到订单创建消息: routingKey={}, order={}", routingKey, order.getId());
​
        try {
            // 业务处理
            OrderResult result = orderService.processOrder(order);
​
            // 手动确认
            channel.basicAck(deliveryTag, false);
​
            log.info("订单处理完成: {}", result);
        } catch (OrderValidationException e) {
            // 校验失败,不重试,发送到死信
            log.warn("订单校验失败,移至死信: {}", order.getId());
            channel.basicReject(deliveryTag, false); // requeue=false
        } catch (Exception e) {
            // 其他异常,重新入队等待重试
            log.error("订单处理异常,重新入队: {}", order.getId(), e);
            channel.basicNack(deliveryTag, false, true);
        }
    }
​
    @RabbitListener(queues = "order.notification.queue")
    public void handleNotification(Order order) {
        // 所有订单事件都会触发通知(routing key = "order.*")
        notificationService.sendNotification(order);
    }
​
    @RabbitListener(queues = "order.dead.queue")
    public void handleDeadOrder(Order order) {
        // 死信处理:记录到数据库、告警、人工介入
        log.warn("死信订单,需人工处理: {}", order);
        orderService.saveDeadOrder(order);
    }
}

发送端(Controller):

复制代码
@RestController
@RequestMapping("/orders")
public class OrderController {
​
    @Autowired
    private RabbitTemplate rabbitTemplate;
​
    @PostMapping
    public ResponseEntity<String> createOrder(@RequestBody Order order) {
        CorrelationData correlationData = new CorrelationData(order.getId());
        rabbitTemplate.convertAndSend(
                "order.exchange",
                "order.created",
                order,
                correlationData
        );
        return ResponseEntity.accepted().body("Order submitted: " + order.getId());
    }
​
    // 延迟订单(需安装 delayed message exchange 插件)
    @PostMapping("/delayed")
    public ResponseEntity<String> createDelayedOrder(@RequestBody Order order) {
        rabbitTemplate.convertAndSend(
                "order.exchange",
                "order.delayed",
                order,
                msg -> {
                    msg.getMessageProperties().setDelay(30000); // 30s 延迟
                    return msg;
                }
        );
        return ResponseEntity.accepted().body("Delayed order submitted");
    }
}

14.4 股票交易示例

复制代码
@Component
@Slf4j
public class StockTrading {
​
    // === 市场数据发布者 ===
    @Scheduled(fixedRate = 1000)
    public void publishMarketData() {
        MarketData data = MarketData.random();
        rabbitTemplate.convertAndSend(
                "stock.exchange",
                "market." + data.getSymbol(),
                data
        );
    }
​
    // === 交易指令监听器 ===
    @RabbitListener(queues = "stock.trade.queue")
    public void handleTrade(TradeOrder order) {
        log.info("执行交易: symbol={}, qty={}, price={}",
                order.getSymbol(), order.getQuantity(), order.getPrice());
        // 交易逻辑
    }
​
    // === 行情监听器(Topic Exchange 通配符) ===
    @RabbitListener(queues = "stock.market.queue")
    public void handleMarketData(
            @Payload MarketData data,
            @Header(AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey) {
        log.info("[{}] {}: ¥{}/{}",
                routingKey, data.getSymbol(), data.getPrice(), data.getVolume());
    }
}

15. 组件开发示例

15.1 自定义消息后处理器

复制代码
@Component
public class TraceIdMessagePostProcessor implements MessagePostProcessor {
​
    @Override
    public Message postProcessMessage(Message message) throws AmqpException {
        message.getMessageProperties().setHeader("X-Trace-Id", MDC.get("traceId"));
        message.getMessageProperties().setHeader("X-Timestamp", Instant.now().toString());
        return message;
    }
​
    @Override
    public Message postProcessMessage(Message message, Correlation correlation) {
        return postProcessMessage(message);
    }
}
​
// 使用
template.convertAndSend("exchange", "key", payload, new TraceIdMessagePostProcessor());

15.2 自定义消息转换器

复制代码
public class ProtobufMessageConverter implements MessageConverter {
​
    @Override
    public Message toMessage(Object object, MessageProperties messageProperties)
            throws MessageConversionException {
        if (object instanceof MessageLite) {
            byte[] bytes = ((MessageLite) object).toByteArray();
            messageProperties.setContentType("application/x-protobuf");
            return new Message(bytes, messageProperties);
        }
        throw new MessageConversionException("Unsupported type: " + object.getClass());
    }
​
    @Override
    public Object fromMessage(Message message) throws MessageConversionException {
        // 需要知道目标类型,可通过 header 传递
        String className = message.getMessageProperties().getHeader("__TypeId__");
        // ...
        return null;
    }
}

15.3 自定义 ConnectionFactory 包装器

复制代码
public class MetricsConnectionFactory extends AbstractConnectionFactory {
​
    private final MeterRegistry meterRegistry;
    private final CachingConnectionFactory delegate;
​
    public MetricsConnectionFactory(CachingConnectionFactory delegate,
                                     MeterRegistry meterRegistry) {
        this.delegate = delegate;
        this.meterRegistry = meterRegistry;
    }
​
    @Override
    public Connection createConnection() throws AmqpException {
        Timer.Sample sample = Timer.start(meterRegistry);
        try {
            Connection conn = delegate.createConnection();
            sample.stop(meterRegistry.timer("rabbitmq.connection.create"));
            return conn;
        } catch (AmqpException e) {
            meterRegistry.counter("rabbitmq.connection.error").increment();
            throw e;
        }
    }
}

15.4 RabbitMQ Stream 插件使用

复制代码
// 依赖:spring-rabbit-stream
@Configuration
public class StreamConfig {
​
    @Bean
    public Environment environment() {
        return Environment.builder()
                .host("localhost")
                .port(5552) // Stream 插件端口
                .username("guest")
                .password("guest")
                .build();
    }
​
    @Bean
    public RabbitStreamTemplate streamTemplate(Environment env) {
        RabbitStreamTemplate template = new RabbitStreamTemplate(env, "my-stream");
        // 发送
        template.convertAndSend(message);
        return template;
    }
​
    @RabbitListener(queues = "my-stream")  // Stream 队列
    public void handleStreamMessage(String message) {
        // 处理流消息
    }
}

15.5 日志 Appender(AMQP Logback Appender)

复制代码
<!-- logback-spring.xml -->
<appender name="AMQP" class="org.springframework.amqp.rabbit.logback.AmqpAppender">
    <host>localhost</host>
    <port>5672</port>
    <username>guest</username>
    <password>guest</password>
    <virtualHost>/</virtualHost>
    <exchangeName>logs.exchange</exchangeName>
    <routingKeyPattern>app.%level</routingKeyPattern>
    <declareExchange>true</declareExchange>
    <applicationId>my-service</applicationId>
    <charset>UTF-8</charset>
    <durable>true</durable>
</appender>

16. 最佳实践清单

连接管理

  • 使用 CachingConnectionFactory 管理连接/Channel 缓存,避免频繁创建

  • 启用发布者确认publisher-confirm-type: correlated)和发布者返回publisher-returns: true

  • 配置 Channel 缓存大小,生产环境建议 50-100

  • 启用心跳requested-heartbeat: 60s),防止空闲连接被中间网络设备断开

  • 集群部署 使用 addresses 属性,避免单点

  • 启用自动恢复,Broker 重启后自动重连

消息发送

  • 使用 convertAndSend(),让消息转换器处理序列化

  • 设置 CorrelationData,将业务 ID(如订单号)关联到确认回调

  • 实现 ConfirmCallback 和 ReturnsCallback,监控消息是否成功到达 Broker

  • 批量发送 使用 BatchingRabbitTemplate 减少网络开销

  • 传递头信息 使用 MessagePostProcessor,如 trace-id、timestamp

消息接收

  • 使用 @RabbitListener 替代编程式监听,代码更简洁

  • 选择合适的容器:Simple(事务/多队列)vs Direct(高吞吐/低延迟)

  • 合理设置并发concurrency(初始 3-5)、max-concurrency(峰值 10-20)

  • 合理设置 prefetch:高吞吐场景 100-500,低延迟场景 1-10

  • 批处理场景 启用 batchListener=trueconsumerBatchEnabled=true

  • 手动确认模式(MANUAL) 在处理成功后显式 ACK

消息序列化

  • 使用 Jackson2JsonMessageConverter 作为默认转换器

  • 生产环境限制信任包setTrustedPackages),防止反序列化漏洞

  • 通过消息头传递类型信息__TypeId__),确保类型安全反序列化

  • ContentTypeDelegatingMessageConverter 支持多格式消息路由

异常处理与重试

  • 区分可重试异常与致命异常:临时异常重试,业务校验失败直接拒绝

  • 使用指数退避(exponential backoff) 代替固定间隔重试

  • 配置死信队列(DLX):重试耗尽后的消息进入死信,便于排查和补偿

  • 使用 RepublishMessageRecoverer 自动将失败消息重新发布

  • 重试次数建议 3-5 次,总退避时间不超过消息 TTL

事务

  • 需要原子性操作时才使用事务(如多个队列的发送必须在同一事务中)

  • 事务性能开销大,优先使用发布者确认 + 手动 ACK 保障可靠性

  • SimpleMessageListenerContainer 支持事务,Direct 不支持

Broker 配置

  • 使用 Builder APIExchangeBuilderQueueBuilder)声明资源

  • 队列设置为持久化durable=true),消息持久化发送

  • Quorum Queue 替代 Classic Mirrored Queue(RabbitMQ 3.8+)

  • 设置队列 TTL 和最大长度,防止消息堆积

  • 使用 RabbitAdmin 的自动声明,Broker 恢复后自动重建拓扑

监控与运维

  • 引入 Micrometer,监控消息发送/消费速率、延迟、错误率

  • BrokerEventListener 监听 Broker 可用性变化

  • 死信队列监控告警:DLQ 中有消息即告警

  • 连接池监控:Channel 获取超时、连接创建失败计数

测试

  • 单元测试 使用 TestRabbitTemplateRabbitListenerTestHarness

  • 集成测试 使用 @SpringRabbitTest + @RabbitAvailable(JUnit5)

  • Mock RabbitTemplate 在 Service 层测试中隔离 AMQP 依赖

安全

  • 启用 SSL/TLS 加密传输

  • 限制 Jackson 反序列化信任包

  • 使用单独的用户凭据,按最小权限原则分配 vhost 权限

  • 生产环境关闭管理端口公网访问(15672)


附录:Maven 完整依赖

复制代码
<dependencies>
    <!-- Spring AMQP 核心 -->
    <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit</artifactId>
        <version>3.0.4</version>
    </dependency>
​
    <!-- RabbitMQ Stream 插件支持 -->
    <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit-stream</artifactId>
        <version>3.0.4</version>
    </dependency>
​
    <!-- Jackson JSON 支持 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
​
    <!-- Spring Retry(重试支持) -->
    <dependency>
        <groupId>org.springframework.retry</groupId>
        <artifactId>spring-retry</artifactId>
    </dependency>
​
    <!-- Micrometer(可观测性) -->
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-core</artifactId>
    </dependency>
​
    <!-- Spring Boot Starter(推荐) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
​
    <!-- 测试 -->
    <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

参考资料: