Spring Boot 4.0 整合 RabbitMQ 注解方式使用指南

Spring Boot 4.0 整合 RabbitMQ 注解方式使用指南

我将基于最新的 Spring Boot 4.x 版本(包含 Spring Framework 6.0 的新特性)为您演示 RabbitMQ 的注解整合方式。这些内容同样适用于未来的 Spring Boot 4.0。

1. 环境准备

1.1 创建项目

xml 复制代码
<!-- pom.xml 主要依赖 -->
<dependencies>
    <!-- Spring Boot 4.x -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- 可选: 消息转换器 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
</dependencies>

2. 基础配置

2.1 配置文件

yaml 复制代码
# application.yml
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    # 连接池配置 (Spring Boot 3.x 新特性)
    connection-timeout: 5s
    # 发布确认
    publisher-confirm-type: correlated
    publisher-returns: true
    template:
      mandatory: true
    listener:
      simple:
        acknowledge-mode: manual  # 手动确认
        retry:
          enabled: true
          max-attempts: 3
          initial-interval: 2s

3. 注解方式实现

3.1 声明队列、交换机和绑定

typescript 复制代码
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {
    
    // 1. 声明队列 (使用新版的Builder模式)
    @Bean
    public Queue orderQueue() {
        return QueueBuilder.durable("order.queue")
                .deadLetterExchange("dlx.exchange")
                .deadLetterRoutingKey("order.dl")
                .ttl(10000)  // 10秒过期
                .maxLength(1000)
                .build();
    }
    
    @Bean
    public Queue dlQueue() {
        return QueueBuilder.durable("dl.order.queue").build();
    }
    
    // 2. 声明交换机
    @Bean
    public DirectExchange orderExchange() {
        return ExchangeBuilder
                .directExchange("order.exchange")
                .durable(true)
                .build();
    }
    
    @Bean
    public DirectExchange dlxExchange() {
        return ExchangeBuilder
                .directExchange("dlx.exchange")
                .durable(true)
                .build();
    }
    
    // 3. 声明绑定
    @Bean
    public Binding orderBinding(Queue orderQueue, DirectExchange orderExchange) {
        return BindingBuilder
                .bind(orderQueue)
                .to(orderExchange)
                .with("order.routing.key");
    }
    
    @Bean
    public Binding dlBinding(Queue dlQueue, DirectExchange dlxExchange) {
        return BindingBuilder
                .bind(dlQueue)
                .to(dlxExchange)
                .with("order.dl");
    }
    
    // 4. 延迟队列插件 (RabbitMQ 延迟消息插件)
    @Bean
    public Queue delayedQueue() {
        return QueueBuilder.durable("delayed.queue")
                .withArgument("x-delayed-type", "direct")
                .build();
    }
    
    @Bean
    public CustomExchange delayedExchange() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(
            "delayed.exchange", 
            "x-delayed-message", 
            true, 
            false, 
            args
        );
    }
}

3.2 生产者服务

typescript 复制代码
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.UUID;

@Service
public class MessageProducer {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    /**
     * 发送简单消息
     */
    public void sendSimpleMessage(String message) {
        rabbitTemplate.convertAndSend(
            "order.exchange", 
            "order.routing.key", 
            message
        );
    }
    
    /**
     * 发送对象消息
     */
    public void sendOrderMessage(Order order) {
        rabbitTemplate.convertAndSend(
            "order.exchange", 
            "order.routing.key", 
            order,
            message -> {
                // 设置消息属性
                message.getMessageProperties()
                    .setContentType("application/json");
                return message;
            }
        );
    }
    
    /**
     * 发送确认消息
     */
    public void sendConfirmMessage(String message) {
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        
        rabbitTemplate.convertAndSend(
            "order.exchange", 
            "order.routing.key", 
            message,
            correlationData
        );
    }
    
    /**
     * 发送延迟消息
     */
    public void sendDelayedMessage(String message, int delayMillis) {
        Message msg = MessageBuilder
            .withBody(message.getBytes())
            .setHeader("x-delay", delayMillis)
            .build();
            
        rabbitTemplate.send(
            "delayed.exchange", 
            "delayed.routing.key", 
            msg
        );
    }
    
    /**
     * 发布者确认回调
     */
    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                System.out.println("消息发送成功: " + correlationData);
            } else {
                System.out.println("消息发送失败: " + cause);
            }
        });
        
        rabbitTemplate.setReturnsCallback(returned -> {
            System.out.println("消息路由失败: " + returned.getMessage());
        });
    }
}

3.3 消费者服务

less 复制代码
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;
import java.io.IOException;

@Component
@RabbitListener(
    bindings = @QueueBinding(
        value = @Queue(
            value = "order.queue",
            arguments = {
                @Argument(name = "x-dead-letter-exchange", value = "dlx.exchange"),
                @Argument(name = "x-dead-letter-routing-key", value = "order.dl"),
                @Argument(name = "x-message-ttl", value = "10000", type = "java.lang.Long")
            }
        ),
        exchange = @Exchange(value = "order.exchange", type = ExchangeTypes.DIRECT),
        key = "order.routing.key"
    )
)
public class MessageConsumer {
    
    /**
     * 基础消息消费
     */
    @RabbitHandler
    public void process(@Payload String message) {
        System.out.println("收到消息: " + message);
    }
    
    /**
     * 对象消息消费
     */
    @RabbitHandler
    public void processOrder(@Payload Order order) {
        System.out.println("收到订单: " + order);
    }
    
    /**
     * 手动确认消息
     */
    @RabbitListener(queues = "manual.queue")
    public void processManual(Message message, Channel channel) throws IOException {
        try {
            System.out.println("处理消息: " + new String(message.getBody()));
            
            // 业务处理
            // ...
            
            // 手动确认
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            
        } catch (Exception e) {
            // 消息重入队列
            channel.basicNack(
                message.getMessageProperties().getDeliveryTag(), 
                false, 
                true
            );
        }
    }
    
    /**
     * 死信队列监听
     */
    @RabbitListener(queues = "dl.order.queue")
    public void processDlMessage(String message) {
        System.out.println("死信队列收到消息: " + message);
    }
    
    /**
     * 延迟消息监听
     */
    @RabbitListener(queues = "delayed.queue")
    public void processDelayedMessage(String message) {
        System.out.println("收到延迟消息: " + message);
    }
}

4. 高级特性示例

4.1 批量消费者

typescript 复制代码
@Component
public class BatchConsumer {
    
    /**
     * 批量消费 (Spring Boot 3.x 新特性优化)
     */
    @RabbitListener(
        queues = "batch.queue",
        containerFactory = "batchContainerFactory"
    )
    public void processBatch(List<Message> messages) {
        for (Message message : messages) {
            System.out.println("批量处理消息: " + new String(message.getBody()));
        }
    }
}

4.2 批量容器工厂配置

dart 复制代码
@Configuration
public class BatchRabbitConfig {
    
    @Bean
    public SimpleRabbitListenerContainerFactory batchContainerFactory(
            SimpleRabbitListenerContainerFactoryConfigurer configurer,
            ConnectionFactory connectionFactory) {
        
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        
        // 开启批量消费
        factory.setBatchListener(true);
        factory.setConsumerBatchEnabled(true);
        factory.setBatchSize(10);  // 每批10条
        factory.setReceiveTimeout(3000L);  // 接收超时3秒
        
        return factory;
    }
}

4.3 消息转换器配置

java 复制代码
@Configuration
public class MessageConverterConfig {
    
    @Bean
    public MessageConverter messageConverter() {
        // 使用Jackson2JsonMessageConverter替代默认的SimpleMessageConverter
        Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
        converter.setUseProjectionForInterfaces(true);  // 支持接口投影
        converter.setUseJavaTypeForMapper(true);
        return converter;
    }
    
    @Bean
    public RabbitTemplate rabbitTemplate(
            ConnectionFactory connectionFactory,
            MessageConverter messageConverter) {
        
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(messageConverter);
        
        // 开启返回模式
        template.setMandatory(true);
        
        return template;
    }
}

5. 完整应用示例

5.1 控制层

less 复制代码
@RestController
@RequestMapping("/rabbitmq")
public class RabbitMQController {
    
    @Autowired
    private MessageProducer messageProducer;
    
    @PostMapping("/send")
    public String sendMessage(@RequestParam String message) {
        messageProducer.sendSimpleMessage(message);
        return "消息发送成功";
    }
    
    @PostMapping("/send-order")
    public String sendOrder(@RequestBody Order order) {
        messageProducer.sendOrderMessage(order);
        return "订单消息发送成功";
    }
    
    @PostMapping("/send-delayed")
    public String sendDelayed(
            @RequestParam String message,
            @RequestParam int delaySeconds) {
        messageProducer.sendDelayedMessage(message, delaySeconds * 1000);
        return "延迟消息发送成功";
    }
}

5.2 实体类

less 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {
    private String orderId;
    private String orderNo;
    private BigDecimal amount;
    private LocalDateTime createTime;
}

6. 测试验证

6.1 测试类

typescript 复制代码
@SpringBootTest
class RabbitmqApplicationTests {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Test
    void testSendAndReceive() {
        // 发送消息
        rabbitTemplate.convertAndSend(
            "order.exchange", 
            "order.routing.key", 
            "Hello RabbitMQ"
        );
        
        // 接收消息
        Object message = rabbitTemplate.receiveAndConvert("order.queue", 3000);
        assertNotNull(message);
    }
    
    @Test
    void testObjectMessage() {
        Order order = new Order("123", "ORD2023001", new BigDecimal("100.00"), LocalDateTime.now());
        rabbitTemplate.convertAndSend("order.exchange", "order.routing.key", order);
    }
}

7. 最佳实践建议

7.1 消息确认策略

  • 生产环境建议开启 publisher-confirmspublisher-returns
  • 消费者根据业务需要选择自动确认或手动确认

7.2 错误处理

kotlin 复制代码
@Component
public class RabbitMQErrorHandler {
    
    /**
     * 全局异常处理
     */
    @Bean
    public RabbitListenerErrorHandler rabbitListenerErrorHandler() {
        return (amqpMessage, message, exception) -> {
            // 记录错误日志
            System.err.println("RabbitMQ 消息处理异常: " + exception.getMessage());
            
            // 可以根据异常类型进行不同处理
            if (exception instanceof BusinessException) {
                // 业务异常,记录但不重试
                return null;
            } else {
                // 系统异常,抛出以触发重试
                throw exception;
            }
        };
    }
}

7.3 监控和指标

yaml 复制代码
management:
  endpoints:
    web:
      exposure:
        include: health,metrics,rabbit
  metrics:
    export:
      rabbit:
        enabled: true

总结

通过以上注解方式的实现,您可以:

  1. 快速上手:通过简单的注解即可实现消息的发送和接收
  2. 高级特性:支持延迟消息、死信队列、批量消费等高级功能
  3. 可靠性:支持发布确认、消费确认、重试机制
  4. 维护性:配置集中管理,代码结构清晰
  5. 可扩展:易于添加新队列和消费者
相关推荐
ServBay1 小时前
Django 6.0 发布,新增原生任务队列与 CSP 支持
后端·python·django
PPPPickup1 小时前
easychat---创建,获取,获取详细,退群,解散,添加与移除群组
java·开发语言·后端·maven
回家路上绕了弯2 小时前
大表优化实战指南:从千万到亿级数据的性能蜕变
分布式·后端
Home2 小时前
23 种设计模式--桥接(Bridge)模式(结构型模式二)
java·后端
编程修仙2 小时前
第九篇 Spring中的代理思想
java·后端·spring
aiopencode2 小时前
iOS CPU 使用率深度分析,多工具协同定位高占用瓶颈的工程化方法
后端
I'm Jie2 小时前
告别重复编码!SpringBoot 字段变更(新旧值)日志工具类的规范化设计与优雅实现
java·spring boot·后端
开心猴爷2 小时前
Bundle Id 创建与管理的工程化方法,一次团队多项目协作中的流程重构
后端
databook2 小时前
用样本猜总体的秘密武器,4大抽样分布总结
后端·python·数据分析