springboot+rabbitmq简单实战
1. 系统环境
jdk1.8、springboot2.7.18
2. 配置 Spring Boot 项目
在 pom.xml 中添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
3. 配置 RabbitMQ
在 application.properties 中配置 RabbitMQ 连接信息:
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
rabbitmq的四种交换机类型
接下来的步骤,根据选择的交换机类型会有所区别。
| 交换机类型 | 类名(Java 中) | 描述 |
|---|---|---|
| Direct Exchange | DirectExchange | 基于精确匹配的路由规则。 |
| Fanout Exchange | FanoutExchange | 广播模式,将消息发送到所有绑定到该交换机的队列。 |
| Topic Exchange | TopicExchange | 基于通配符匹配的路由规则,灵活性高。 |
| Headers Exchange | HeadersExchange | 基于消息头(Headers)的路由规则,不常用。 |
直连交换机
根据路由规则,精确匹配路由键发送消息到指定队列。
4. 创建队列和交换机
创建一个配置类:
这个例子采用的是直连交换机
import com.example.springbootrabbitmq.constant.Common;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* rabbit mq配置,定义队列、交换机、绑定关系
*/
@Configuration
public class HelloConfig {
/**
* 创建一个非持久的队列:hello
* @return -
*/
@Bean
public Queue helloQueue() {
QueueBuilder queueBuilder = QueueBuilder.nonDurable(Common.HELLO_QUEUE_NAME);//创建一个非持久的队列
// QueueBuilder queueBuilder2 = QueueBuilder.durable(Common.HELLO_QUEUE_NAME);//创建一个持久化的队列
queueBuilder.autoDelete();//队列自动删除
// queueBuilder.exclusive();//队列排他,只能被一个连接使用。
return queueBuilder.build();//创建队列
}
/**
* 创建一个直连交换机:hello
* @return - 默认的交换机类型为direct
*/
@Bean
public DirectExchange helloExchange() {
return new DirectExchange(Common.HELLO_EXCHANGE_NAME);
}
/**
* 创建一个绑定关系:hello-exchange和hello-queue
* @return -
*/
@Bean
Binding helloBinding(Queue helloQueue,DirectExchange helloExchange) {
return BindingBuilder.bind(helloQueue).to(helloExchange).with(Common.HELLO_ROUTING_KEY);
}
}
5. 创建消息生产者
根据路由规则,精确匹配路由键发送消息到指定队列。
创建一个消息生产者:
import com.example.springbootrabbitmq.constant.Common;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
/**
* 消息生产者
*/
@Component
public class HelloSender {
private static final Logger logger = LoggerFactory.getLogger(HelloSender.class);
@Resource
private AmqpTemplate rabbitTemplate;
public void send() {
String context = "hello " + new Date();
logger.info("Sender : " + context);
this.rabbitTemplate.convertAndSend(Common.HELLO_EXCHANGE_NAME, Common.HELLO_ROUTING_KEY, context);
}
}
6. 创建消息消费者
使用注解@RabbitListener、@RabbitHandler创建一个消费者类 :
@Component的作用是将组件注入spring容器中。
import com.example.springbootrabbitmq.constant.Common;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 接收hello队列消息的消费者
*/
@Component
@RabbitListener(queues = Common.HELLO_QUEUE_NAME)//监听hello队列
public class HelloReceiver {
private static final Logger logger = LoggerFactory.getLogger(HelloReceiver.class);
@RabbitHandler//监听hello队列的消息
public void process(String hello) {
logger.info("Receiver : " + hello);
}
}
TOPIC交换机
基于通配符匹配的路由规则,匹配路由键发送消息到指定队列。
4. 创建队列和交换机
创建一个配置类:
import com.example.springbootrabbitmq.constant.Common;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 配置队列1、队列2、Topic Exchange和绑定关系
*/
@Configuration
public class TopicConfig {
/**
* 创建队列1
* @return -
*/
@Bean
public Queue topicQueue1(){
return new Queue(Common.TOPIC_QUEUE_NAME1);
}
/**
* 创建队列2
* @return -
*/
@Bean
public Queue topicQueue2(){
return new Queue(Common.TOPIC_QUEUE_NAME2);
}
/**
* 创建队列3
* @return -
*/
@Bean
public Queue topicQueue3(){
return new Queue(Common.TOPIC_QUEUE_NAME3);
}
/**
* 创建topic类型交换机
* @return -
*/
@Bean
public TopicExchange topicExchange(){
return new TopicExchange(Common.TOPIC_EXCHANGE_NAME);
}
/**
* 绑定队列1和交换机
* @param topicQueue1 -
* @param topicExchange -
* @return -
*/
@Bean
public Binding binding1(Queue topicQueue1, TopicExchange topicExchange){
return BindingBuilder.bind(topicQueue1).to(topicExchange).with(Common.TOPIC_ROUTING_KEY);
}
/**
* 绑定队列2和交换机
* @param topicQueue2 -
* @param topicExchange -
* @return -
*/
@Bean
public Binding binding2(Queue topicQueue2, TopicExchange topicExchange){
return BindingBuilder.bind(topicQueue2).to(topicExchange).with(Common.TOPIC_ROUTING_KEY_ALL);
}
/**
* 绑定队列3和交换机
* @param topicQueue3 -
* @param topicExchange -
* @return -
*/
@Bean
public Binding binding3(Queue topicQueue3, TopicExchange topicExchange){
return BindingBuilder.bind(topicQueue3).to(topicExchange).with(Common.TOPIC_ROUTING_KEY_ONE);
}
}
5. 创建消息生产者
基于通配符匹配的路由规则,匹配路由键发送消息到指定队列。
import com.example.springbootrabbitmq.constant.Common;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* Topic消息生产者
* 路由规则:基于通配符匹配的路由规则。路由键和绑定键可以使用通配符进行匹配。
* (星号):匹配一个单词(单词之间用 . 分隔)。
* (井号):匹配零个或多个单词。
*/
@Component
public class TopicSender {
private static final Logger logger = LoggerFactory.getLogger(TopicSender.class);
@Resource
private AmqpTemplate rabbitTemplate;
/**
* 发送消息至队列1、队列2、队列3
*/
public void send() {
String context = "hello , 这条消息将发给队列1、队列2、队列3";
logger.info("Sender : " + context);
this.rabbitTemplate.convertAndSend(Common.TOPIC_EXCHANGE_NAME, "topic.route.key", context);
}
/**
* 发送消息至队列2、队列3
*/
public void send2() {
String context = "hello , 这条消息将发给队列2、队列3";
logger.info("Sender : " + context);
this.rabbitTemplate.convertAndSend(Common.TOPIC_EXCHANGE_NAME, "topic.route.222", context);
}
/**
* 发送消息至队列2
*/
public void send3() {
String context = "hello , 这条消息将发给队列2";
logger.info("Sender : " + context);
this.rabbitTemplate.convertAndSend(Common.TOPIC_EXCHANGE_NAME, "topic.route.key.queue2", context);
}
}
6. 创建消息消费者
使用注解@RabbitListener、@RabbitHandler创建一个消费者类 :
@Component的作用是将组件注入spring容器中。
接收队列1消息的消费者:
import com.example.springbootrabbitmq.constant.Common;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 接收队列1消息的消费者
*/
@Component
@RabbitListener(queues = Common.TOPIC_QUEUE_NAME1)//监听topicQueue1队列
public class TopicReceiver1 {
private static final Logger logger = LoggerFactory.getLogger(TopicReceiver1.class);
@RabbitHandler
public void process(String hello) {
logger.info("Receiver : " + hello);
}
}
接收队列2消息的消费者:
import com.example.springbootrabbitmq.constant.Common;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 接收队列2消息的消费者
*/
@Component
@RabbitListener(queues = Common.TOPIC_QUEUE_NAME2)//监听topicQueue2队列
public class TopicReceiver2 {
private static final Logger logger = LoggerFactory.getLogger(TopicReceiver2.class);
@RabbitHandler//监听topicQueue2队列的消息
public void process(String hello) {
logger.info("Receiver : " + hello);
}
}
接收队列3消息的消费者
import com.example.springbootrabbitmq.constant.Common;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 接收队列3消息的消费者
*/
@Component
@RabbitListener(queues = Common.TOPIC_QUEUE_NAME3)//监听topicQueue3队列
public class TopicReceiver3 {
private static final Logger logger = LoggerFactory.getLogger(TopicReceiver3.class);
@RabbitHandler//监听topicQueue3队列的消息
public void process(String hello) {
logger.info("Receiver : " + hello);
}
}
FANOUT交换机
忽略路由键(Routing Key),将消息广播到所有绑定到该交换机的队列。
4. 创建队列和交换机
创建一个配置类:
import com.example.springbootrabbitmq.constant.Common;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 广播模式,将消息发送到所有绑定到该交换机的队列。
*/
@Configuration
public class FanoutRabbitConfig {
/**
* 创建队列A
* @return
*/
@Bean
public Queue AMessage() {
return new Queue(Common.FAN_OUT_QUEUE_A);
}
/**
* 创建队列B
* @return
*/
@Bean
public Queue BMessage() {
return new Queue(Common.FAN_OUT_QUEUE_B);
}
/**
* 创建队列C
* @return
*/
@Bean
public Queue CMessage() {
return new Queue(Common.FAN_OUT_QUEUE_C);
}
/**
* 创建Fanout Exchange
* @return
*/
@Bean
FanoutExchange fanoutExchange() {
return new FanoutExchange(Common.FAN_OUT_EXCHANGE);
}
/**
* 绑定队列A到Fanout Exchange
* @param AMessage
* @param fanoutExchange
* @return
*/
@Bean
Binding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange) {
return BindingBuilder.bind(AMessage).to(fanoutExchange);
}
/**
* 绑定队列B到Fanout Exchange
* @param BMessage
* @param fanoutExchange
* @return
*/
@Bean
Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(BMessage).to(fanoutExchange);
}
/**
* 绑定队列C到Fanout Exchange
* @param CMessage
* @param fanoutExchange
* @return
*/
@Bean
Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(CMessage).to(fanoutExchange);
}
}
5. 创建消息生产者
忽略路由键(Routing Key),将消息广播到所有绑定到该交换机的队列。
import com.example.springbootrabbitmq.constant.Common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 忽略路由规则,广播给所有消费者的生产者
*/
@Slf4j
@Component
public class FanoutSender {
@Resource
private AmqpTemplate rabbitTemplate;
public void send() {
String context = "hi, fanout msg ";
log.info("Sender : " + context);
this.rabbitTemplate.convertAndSend(Common.FAN_OUT_EXCHANGE,"", context);
}
}
6. 创建消息消费者
使用注解@RabbitListener、@RabbitHandler创建一个消费者类 :
@Component的作用是将组件注入spring容器中。
消费者A:
import com.example.springbootrabbitmq.constant.Common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 消费者A
*/
@Slf4j
@Component
@RabbitListener(queues = Common.FAN_OUT_QUEUE_A)//监听fanout.A队列
public class FanoutReceiverA {
@RabbitHandler//监听fanout.A队列的消息
public void process(String message) {
log.info("fanout Receiver A : " + message);
}
}
消费者B:
import com.example.springbootrabbitmq.constant.Common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 消费者B
*/
@Slf4j
@Component
@RabbitListener(queues = Common.FAN_OUT_QUEUE_B)//监听fanout.B队列
public class FanoutReceiverB {
@RabbitHandler//监听fanout.B队列的消息
public void process(String message) {
log.info("fanout Receiver B: " + message);
}
}
消费者C:
import com.example.springbootrabbitmq.constant.Common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 消费者C
*/
@Slf4j
@Component
@RabbitListener(queues = Common.FAN_OUT_QUEUE_C)//监听fanout.C队列
public class FanoutReceiverC {
@RabbitHandler//监听fanout.C队列的消息
public void process(String message) {
log.info("fanout Receiver C: " + message);
}
}
如何实现多消费者、多生产者?
很简单,直接复制多一个相同的生产者或消费者即可。
高级特性
消息确认与限流
在 application.properties 中配置手动签收和限流:
spring.rabbitmq.listener.simple.acknowledge-mode=manual
spring.rabbitmq.listener.simple.prefetch=5
消费者代码中手动签收:
@Component
public class QosConsumer {
@RabbitListener(queues = "my_queue")
public void listenMessage(Message message, Channel channel) throws IOException, InterruptedException {
System.out.println(new String(message.getBody()));
Thread.sleep(3000); // 模拟业务处理
channel.basicAck(message.getMessageProperties().getDeliveryTag(), true); // 手动签收
}
}
消息存活时间(TTL)
设置队列或消息的 TTL:
@Bean
public Queue getMessageQueue2() {
return QueueBuilder.durable("bootQueue2").ttl(10000).build();
}
死信队列(DLX)
配置死信队列:
@Bean
public Queue normalQueue() {
return QueueBuilder.durable("normal_queue")
.deadLetterExchange("dead_exchange")
.deadLetterRoutingKey("dead_routing")
.ttl(10000)
.maxLength(10)
.build();
}
通过以上步骤,你可以在 Spring Boot 项目中实现 RabbitMQ 的基本功能和高级特性,满足实际项目中的多种需求。

浙公网安备 33010602011771号