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 的基本功能和高级特性,满足实际项目中的多种需求。

posted @ 2025-06-13 23:15  抒写  阅读(114)  评论(0)    收藏  举报