SpringBoot使用RabbitMQ延时队列

本文介绍了如何在SpringBoot中使用RabbitMQ实现延时队列,适用于处理如订单超时和短信通知等场景。首先,文章简述了RabbitMQ的基本概念和特性,然后详细说明了SpringBoot整合RabbitMQ的步骤,包括添加依赖和配置。在使用Topic模式下,文章阐述了创建队列、交换机和绑定关系,以及生产者和消费者的消息交互过程。最后,提醒读者在首次运行时需手动在RabbitMQ管理界面添加exchange以避免错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringBoot使用RabbitMQ延时队列

RabbitMQ简介

AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

延时队列

延时队列的使用场景:

1.订单业务:在电商中,用户下单后30分钟后未付款则取消订单。

2.短信通知:用户下单并付款后,1分钟后发短信给用户。

SpringBoot整合RabbitMQ

添加依赖

1、在 pom.xml 中添加 spring-boot-starter-amqp的依赖

	
	<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>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>

2、在 application.properties文件中配置rabbitmq相关内容

    #对于rabbitMQ的支持
    spring.rabbitmq.host=127.0.0.1
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=guest
    spring.rabbitmq.password=guest

使用Topic模式

1、初始化queue exchange和queue及exchange之间的binding关系

    import org.springframework.amqp.core.Binding;
    import org.springframework.amqp.core.BindingBuilder;
    import org.springframework.amqp.core.DirectExchange;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

    import org.springframework.amqp.core.Queue;

    import java.util.HashMap;
    import java.util.Map;
    /**
     * @auther: ***
     * @time: 2019-12-19 11:11
     */
    @Configuration
    public class Config {
        public static final String IMMEDIATE_QUEUE = "queue.demo.immediate";//立即消费的队列名称
        public static final String IMMEDIATE_EXCHANGE = "exchange.demo.immediate";//立即消费的exchange
        public static final String IMMEDIATE_ROUTING_KEY = "routingkey.demo.immediate";//立即消费的routing-key 名称
        public static final String DELAY_QUEUE= "queue.demo.delay";//延时消费的队列名称
        public static final String DEAD_LETTER_EXCHANGE = "exchange.demo.delay";//延时消费的exchange
        public static final String DELAY_ROUTING_KEY = "routingkey.demo.delay";//延时消费的routing-key名称

        // 创建一个立即消费队列
        @Bean
        public Queue immediateQueue() {
            // 第一个参数是创建的queue的名字,第二个参数是是否支持持久化
            return new Queue(IMMEDIATE_QUEUE, true);
        }

        // 创建一个延时队列
        @Bean
        public Queue delayQueue() {
            Map<String, Object> params = new HashMap<>();
            // x-dead-letter-exchange 声明了队列里的死信转发到的DLX名称,
            params.put("x-dead-letter-exchange", IMMEDIATE_EXCHANGE);
            // x-dead-letter-routing-key 声明了这些死信在转发时携带的 routing-key 名称。
            params.put("x-dead-letter-routing-key", IMMEDIATE_ROUTING_KEY);
            return new Queue(DELAY_QUEUE, true, false, false, params);
        }

        public DirectExchange immediateExchange() {
            // 一共有三种构造方法,可以只传exchange的名字, 第二种,可以传exchange名字,是否支持持久化,是否可以自动删除,
            //第三种在第二种参数上可以增加Map,Map中可以存放自定义exchange中的参数
            return new DirectExchange(IMMEDIATE_EXCHANGE, true, false);
        }

        @Bean public DirectExchange deadLetterExchange() {
            // 一共有三种构造方法,可以只传exchange的名字, 第二种,可以传exchange名字,是否支持持久化,是否可以自动删除,
            // 第三种在第二种参数上可以增加Map,Map中可以存放自定义exchange中的参数
            return new DirectExchange(DEAD_LETTER_EXCHANGE, true, false);
        }

        //把立即消费的队列和立即消费的exchange绑定在一起
        @Bean
        public Binding immediateBinding() {
            return BindingBuilder.bind(immediateQueue()).to(immediateExchange()).with(IMMEDIATE_ROUTING_KEY);
        }

        //把延时消费的队列和延时消费的exchange绑定在一起
        @Bean
        public Binding delayBinding() {
            return BindingBuilder.bind(delayQueue()).to(deadLetterExchange()).with(DELAY_ROUTING_KEY);
        }
    }

2、生产者生产消息

    import com.demo01.demo.config.Config;
    import org.springframework.amqp.rabbit.annotation.EnableRabbit;
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Component;

    import java.text.SimpleDateFormat;
    import java.util.Date;

    /**
     * 消费者消费消息
     * @auther: ***	
     * @time: 2019-12-19 11:21
     */
    @Component
    @EnableRabbit
    @Configuration
    public class ImmediateReceiver {
        @RabbitListener(queues = Config.IMMEDIATE_QUEUE)
        @RabbitHandler
        public void get(String msg) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("收到延时消息时间:"+sdf.format(new Date()) + " Delay sent.");
            System.out.println("收到延时消息了:" + msg);
        }
    }

消费者消费消息:

    import com.demo01.demo.config.Config;
    import org.springframework.amqp.rabbit.core.RabbitTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;

    import java.text.SimpleDateFormat;
    import java.util.Date;

    /**
     * @auther: **
     * @time: 2019-12-19 11:20
     */
    @Component
    public class ImmediateSender {
        @Autowired
        private RabbitTemplate rabbitTemplate;

        public void send(String msg, int delayTime) {
            System.out.println("msg="+",delayTime" + delayTime);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            this.rabbitTemplate.convertAndSend(Config.DEAD_LETTER_EXCHANGE, Config.DELAY_ROUTING_KEY, msg, message -> {
                message.getMessageProperties().setExpiration(delayTime + ""); System.out.println(sdf.format(new Date()) + " Delay sent."); return message;
            });
        }
    }

测试类

	import com.demo01.demo.component.ImmediateSender;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;

    import java.util.concurrent.TimeUnit;
    @SpringBootTest
    class DemoApplicationTests {

        @Autowired
        ImmediateSender immediateSender;
        @Test
        public void test() {
            immediateSender.send("我是一个延时消息",30000);//3秒

            //让服务一直挂起,不然,接收消息时,服务已经停了
            while(true){
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }

    }

第一次运行,需要进入rabbitmq管理界面,加上exchange,不然会报错(no exchange ‘exchange.demo.immediate’ in vhost ‘/’)

添加方式:1.浏览器打开:http://127.0.0.1:15672 2.选择Exchanges 3.Add a new exchange ,填写name:exchange.demo.immediate,type选择:direct,点击Add exchange ,完成。

mq管理界面,加上exchange,不然会报错(no exchange ‘exchange.demo.immediate’ in vhost ‘/’)

添加方式:1.浏览器打开:http://127.0.0.1:15672 2.选择Exchanges 3.Add a new exchange ,填写name:exchange.demo.immediate,type选择:direct,点击Add exchange ,完成。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值