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

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

由于 Spring Boot 4.0 目前最新版本,我将基于最新的 Spring Boot 4.x 版本(包含 Spring Framework 6.0 的新特性)演示 RabbitMQ 的注解整合方式。

Spring Cloud全栈实战:手撸企业级项目,从入门到架构师!

1. 环境准备

Spring Cloud全栈实战:手撸企业级项目,从入门到架构师!

1.1 创建项目

xml 复制代码
<!-- pom.xml 主要依赖 -->
<dependencies>
    <!-- Spring Boot 3.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. 基础配置

Spring Cloud全栈实战:手撸企业级项目,从入门到架构师!

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 声明队列、交换机和绑定

java 复制代码
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 生产者服务

java 复制代码
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 消费者服务

java 复制代码
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. 高级特性示例

Spring Cloud全栈实战:手撸企业级项目,从入门到架构师!

4.1 批量消费者

java 复制代码
@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 批量容器工厂配置

java 复制代码
@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 控制层

java 复制代码
@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 实体类

Spring Cloud全栈实战:手撸企业级项目,从入门到架构师!

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

6. 测试验证

6.1 测试类

java 复制代码
@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 错误处理

java 复制代码
@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 监控和指标

Spring Cloud全栈实战:手撸企业级项目,从入门到架构师!

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

总结

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

  1. 快速上手:通过简单的注解即可实现消息的发送和接收
  2. 高级特性:支持延迟消息、死信队列、批量消费等高级功能
  3. 可靠性:支持发布确认、消费确认、重试机制
  4. 维护性:配置集中管理,代码结构清晰
  5. 可扩展:易于添加新队列和消费者

Spring Cloud全栈实战:手撸企业级项目,从入门到架构师!

相关推荐
星辰烈龙1 小时前
黑马程序员Java基础7
java·开发语言
big-seal1 小时前
分页列表中能够按照名称查询,使用 mybatis 的 Example 动态构造 SQL where 条件
java·开发语言
福尔摩斯张1 小时前
C语言文件操作详解(一):文件的打开与关闭(详细)
java·linux·运维·服务器·c语言·数据结构·算法
q_19132846951 小时前
基于Springboot2+Vue2+uniapp的单商家在线点餐外卖小程序
vue.js·spring boot·mysql·小程序·uni-app·计算机毕业设计
廋到被风吹走1 小时前
【Spring】依赖注入的实现方式对比
java·spring
Zzzzzxl_1 小时前
互联网大厂Java/Agent面试实战:Spring Boot、JVM、微服务与AI Agent/RAG场景问答
java·jvm·spring boot·ai·agent·rag·microservices
未若君雅裁1 小时前
JVM高级篇总结笔记
java·jvm·笔记
Ttang231 小时前
【AI篇3】在Java项目中调用大模型API
java·人工智能·microsoft·ai·api
九转苍翎1 小时前
Java外功精要(6)——Spring事务及其传播机制
spring boot