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-confirms和publisher-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
总结
通过以上注解方式的实现,您可以:
- 快速上手:通过简单的注解即可实现消息的发送和接收
- 高级特性:支持延迟消息、死信队列、批量消费等高级功能
- 可靠性:支持发布确认、消费确认、重试机制
- 维护性:配置集中管理,代码结构清晰
- 可扩展:易于添加新队列和消费者