本篇主要记录Spring boot 集成Rabbitmq,分为两部分, 第一部分为创建普通消息队列, 第二部分为延时消息队列实现:

spring boot提供对mq消息队列支持amqp相关包,引入即可:

[html] view plain copy

 
  1. <!-- rabbit mq -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-amqp</artifactId>
  5. </dependency>

属性配置文件application.properties:

[plain] view plain copy

 
  1. #rabbitmq
  2. spring.rabbitmq.host=127.0.0.1
  3. spring.rabbitmq.port=5672
  4. spring.rabbitmq.username=root
  5. spring.rabbitmq.password=root

RabbitMq配置类,配置连接工厂以及操作对象:

[java] view plain copy

 
  1. @Configuration
  2. @ConfigurationProperties(prefix = "spring.rabbitmq")
  3. public class RabbitMQConfiguration {
  4. private static Logger logger = Logger.getLogger(RabbitMQConfiguration.class);
  5. private String host;
  6. private int port;
  7. private String username;
  8. private String password;
  9. // 链接信息
  10. @Bean
  11. public ConnectionFactory connectionFactory() {
  12. CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host, port);
  13. connectionFactory.setUsername(username);
  14. connectionFactory.setPassword(password);
  15. connectionFactory.setVirtualHost("/");
  16. connectionFactory.setPublisherConfirms(true);
  17. logger.info("Create ConnectionFactory bean ..");
  18. return connectionFactory;
  19. }
  20. @Bean
  21. @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  22. public RabbitTemplate rabbitTemplate() {
  23. RabbitTemplate template = new RabbitTemplate(connectionFactory());
  24. return template;
  25. }
  26. //省略getter setter
[java] view plain copy

 
  1. }

定义Service接口如下:

暂时不考虑延时队列,定义发送消息接口

[java] view plain copy

 
  1. /**
  2. *
  3. * @author victor
  4. * @desc 消息队列服务接口
  5. */
  6. public interface IMessageQueueService {
  7. /**
  8. * 发送消息到队列
  9. * @param queue 队列名称
  10. * @param message 消息内容
  11. */
  12. public void send(String queueName,String message);
  13. }

Service实现

[java] view plain copy

 
  1. package com.ks.server.service.impl.queue;
  2. import org.springframework.amqp.AmqpException;
  3. import org.springframework.amqp.core.Message;
  4. import org.springframework.amqp.core.MessagePostProcessor;
  5. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.stereotype.Service;
  8. import com.base.common.codec.JSONUtils;
  9. import com.ks.common.constant.MQConstant;
  10. import com.ks.common.service.queue.IMessageQueueService;
  11. import com.ks.modal.queue.DLXMessage;
  12. /**
  13. *
  14. * @author victor
  15. * @desc 消息队列服务接口实现
  16. */
  17. @Service("messageQueueService")
  18. public class MessageQueueServiceImpl implements IMessageQueueService{
  19. @Autowired
  20. private RabbitTemplate rabbitTemplate;
  21. @Override
  22. public void send(String queueName, String msg) {
  23. rabbitTemplate.convertAndSend(MQConstant.DEFAULT_EXCHANGE,queueName, msg);
  24. }
  25. }

相关常量类:

[java] view plain copy

 
  1. package com.ks.common.constant;
  2. /**
  3. *
  4. * @author victor
  5. * @desc Rabbit消息队列相关常量
  6. */
  7. public final class MQConstant {
  8. private MQConstant(){
  9. }
  10. //exchange name
  11. public static final String DEFAULT_EXCHANGE = "KSHOP";
  12. //DLX QUEUE
  13. public static final String DEFAULT_DEAD_LETTER_QUEUE_NAME = "kshop.dead.letter.queue";
  14. //DLX repeat QUEUE 死信转发队列
  15. public static final String DEFAULT_REPEAT_TRADE_QUEUE_NAME = "kshop.repeat.trade.queue";
  16. //Hello 测试消息队列名称
  17. public static final String HELLO_QUEUE_NAME = "HELLO";
  18. }

到现在为止,队列相关配置,以及使用以及封装完成,接下来是创建队列,

这里我是单独创建一个配置类,用于队列配置, 创建Hello队列示例如下:

[java] view plain copy

 
  1. package com.ks.ons.config;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import org.springframework.amqp.core.Binding;
  5. import org.springframework.amqp.core.BindingBuilder;
  6. import org.springframework.amqp.core.DirectExchange;
  7. import org.springframework.amqp.core.Queue;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.context.annotation.Configuration;
  10. import com.ks.common.constant.MQConstant;
  11. /**
  12. *
  13. * @author victor
  14. * @desc 队列配置
  15. */
  16. @Configuration
  17. public class QueueConfiguration {
  18. //信道配置
  19. @Bean
  20. public DirectExchange defaultExchange() {
  21. return new DirectExchange(MQConstant.DEFAULT_EXCHANGE, true, false);
  22. }
  23. /*********************    hello 队列  测试    *****************/
  24. @Bean
  25. public Queue queue() {
  26. Queue queue = new Queue(MQConstant.HELLO_QUEUE_NAME,true);
  27. return queue;
  28. }
  29. @Bean
  30. public Binding binding() {
  31. return BindingBuilder.bind(queue()).to(defaultExchange()).with(MQConstant.HELLO_QUEUE_NAME);
  32. }
  33. }

通过配置队列bean,在程序启动时会在rabbitmq中创建相关队列,启动程序,可以在rabbtmq管理界面看到信道和队列信息:

众所周知,既然有了队列,用来处理业务的最终还是需要消费者,消费者创建示例如下:

[java] view plain copy

 
  1. package com.ks.ons.processor.hello;
  2. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  3. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  4. import org.springframework.stereotype.Component;
  5. import com.ks.common.constant.MQConstant;
  6. /**
  7. *
  8. * @author victor
  9. * @desc hello 消息队列消费者
  10. */
  11. @Component
  12. @RabbitListener(queues = MQConstant.HELLO_QUEUE_NAME)
  13. public class HelloProcessor {
  14. @RabbitHandler
  15. public void process(String content) {
  16. System.out.println("接受消息:" + content);
  17. }
  18. }

注入service

[java] view plain copy

 
  1. @Autowired
  2. private IMessageQueueService messageQueueService;

发送消息

[java] view plain copy

 
  1. messageQueueService.send(MQConstant.HELLO_QUEUE_NAME, "测试发送消息");

接下来展示如何实现延时队列,在此之前如果读者像我一样对rabbitmq队列了解程度并不深入的话,-->推荐文章, 可以对rabbitmq延时队列实现思路有大概了解.

在本文中,主要是通过rabbitmq的DLX特性来实现发送延时队列:

思路如下:

客户端:指具体往MQ发生消息端, 客户端将消息内容进行自定义包装, 将消息中附带目标队列名称。如:客户端向队列Q1发送字符串“hello” , 延时时间为60秒, 包装后修改为{"queueName":"Q1","body": “hello”},此时,将消息发送到DLX死信队列,而非Q1队列,并将消息设置为60秒超时。

DLX:死信队列,用来存储有超时时间信息的消息, 并且可以设置当消息超时时,转发到另一个指定队列(此处设置转发到router), 无消费者,当接收到客户端消息之后,等待消息超时,将消息转发到指定的Router队列

Router: 转发队列,用来接收死信队列超时消息, 如上示例消息,在接收到之后,消费者将消息解析,获取queueName,body,再向所获取的queueName队列发送一条消息,内容为body.

Q1,Q2,Q3.: 用户业务队列,当Q1收到hello,已经是60秒之后,再进行消费

修改上面代码 , 新增两个队列,

死信队列:存放发送的延时消息,

路由转发队列:用于接受死信消息死亡, 并将消息转发到业务目标队列

修改之后代码如下:

[java] view plain copy

 
  1. /**
  2. *
  3. * @author victor
  4. * @desc 队列配置
  5. */
  6. @Configuration
  7. public class QueueConfiguration {
  8. //信道配置
  9. @Bean
  10. public DirectExchange defaultExchange() {
  11. return new DirectExchange(MQConstant.DEFAULT_EXCHANGE, true, false);
  12. }
  13. @Bean
  14. public Queue repeatTradeQueue() {
  15. Queue queue = new Queue(MQConstant.DEFAULT_REPEAT_TRADE_QUEUE_NAME,true,false,false);
  16. return queue;
  17. }
  18. @Bean
  19. public Binding  drepeatTradeBinding() {
  20. return BindingBuilder.bind(repeatTradeQueue()).to(defaultExchange()).with(MQConstant.DEFAULT_REPEAT_TRADE_QUEUE_NAME);
  21. }
  22. @Bean
  23. public Queue deadLetterQueue() {
  24. Map<String, Object> arguments = new HashMap<>();
  25. arguments.put("x-dead-letter-exchange", MQConstant.DEFAULT_EXCHANGE);
  26. arguments.put("x-dead-letter-routing-key", MQConstant.DEFAULT_REPEAT_TRADE_QUEUE_NAME);
  27. Queue queue = new Queue(MQConstant.DEFAULT_DEAD_LETTER_QUEUE_NAME,true,false,false,arguments);
  28. System.out.println("arguments :" + queue.getArguments());
  29. return queue;
  30. }
  31. @Bean
  32. public Binding  deadLetterBinding() {
  33. return BindingBuilder.bind(deadLetterQueue()).to(defaultExchange()).with(MQConstant.DEFAULT_DEAD_LETTER_QUEUE_NAME);
  34. }
  35. /*********************    hello 队列  测试    *****************/
  36. @Bean
  37. public Queue queue() {
  38. Queue queue = new Queue(MQConstant.HELLO_QUEUE_NAME,true);
  39. return queue;
  40. }
  41. @Bean
  42. public Binding binding() {
  43. return BindingBuilder.bind(queue()).to(defaultExchange()).with(MQConstant.HELLO_QUEUE_NAME);
  44. }
  45. }

修改Service服务:

[java] view plain copy

 
  1. package com.ks.common.service.queue;
  2. /**
  3. *
  4. * @author victor
  5. * @desc 消息队列服务接口
  6. */
  7. public interface IMessageQueueService {
  8. /**
  9. * 发送消息到队列
  10. * @param queue 队列名称
  11. * @param message 消息内容
  12. */
  13. public void send(String queueName,String message);
  14. /**
  15. * 延迟发送消息到队列
  16. * @param queue 队列名称
  17. * @param message 消息内容
  18. * @param times 延迟时间 单位毫秒
  19. */
  20. public void send(String queueName,String message,long times);
  21. }
[java] view plain copy

 
  1. package com.ks.server.service.impl.queue;
  2. import org.springframework.amqp.AmqpException;
  3. import org.springframework.amqp.core.Message;
  4. import org.springframework.amqp.core.MessagePostProcessor;
  5. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.stereotype.Service;
  8. import com.base.common.codec.JSONUtils;
  9. import com.ks.common.constant.MQConstant;
  10. import com.ks.common.service.queue.IMessageQueueService;
  11. import com.ks.modal.queue.DLXMessage;
  12. /**
  13. *
  14. * @author victor
  15. * @desc 消息队列服务接口实现
  16. */
  17. @Service("messageQueueService")
  18. public class MessageQueueServiceImpl implements IMessageQueueService{
  19. @Autowired
  20. private RabbitTemplate rabbitTemplate;
  21. @Override
  22. public void send(String queueName, String msg) {
  23. rabbitTemplate.convertAndSend(MQConstant.DEFAULT_EXCHANGE,queueName, msg);
  24. }
  25. @Override
  26. public void send(String queueName, String msg, long times) {
  27. DLXMessage dlxMessage = new DLXMessage(queueName,msg,times);
  28. MessagePostProcessor processor = new MessagePostProcessor(){
  29. @Override
  30. public Message postProcessMessage(Message message) throws AmqpException {
  31. message.getMessageProperties().setExpiration(times + "");
  32. return message;
  33. }
  34. };
  35. dlxMessage.setExchange(MQConstant.DEFAULT_EXCHANGE);
  36. rabbitTemplate.convertAndSend(MQConstant.DEFAULT_EXCHANGE,MQConstant.DEFAULT_DEAD_LETTER_QUEUE_NAME, JSONUtils.toJson(dlxMessage), processor);
  37. }
  38. }

JSONUtils 为一个JSON工具类

新增消息实体,用于包装消息:

[java] view plain copy

 
  1. package com.ks.modal.queue;
  2. import java.io.Serializable;
  3. /**
  4. *
  5. * @author victor
  6. * @desc rabbit 死信消息载体
  7. */
  8. public class DLXMessage implements Serializable {
  9. private static final long serialVersionUID = 9956432152000L;
  10. public DLXMessage() {
  11. super();
  12. }
  13. public DLXMessage(String queueName, String content, long times) {
  14. super();
  15. this.queueName = queueName;
  16. this.content = content;
  17. this.times = times;
  18. }
  19. public DLXMessage(String exchange, String queueName, String content, long times) {
  20. super();
  21. this.exchange = exchange;
  22. this.queueName = queueName;
  23. this.content = content;
  24. this.times = times;
  25. }
  26. private String exchange;
  27. private String queueName;
  28. private String content;
  29. private long times;
  30. //省略getter setter
  31. }

路由转发队列消费者实现,负责接收超时消息,进行转发:

[java] view plain copy

 
  1. package com.ks.ons.processor.system;
  2. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  3. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Component;
  6. import com.base.common.codec.JSONUtils;
  7. import com.ks.common.constant.MQConstant;
  8. import com.ks.common.service.queue.IMessageQueueService;
  9. import com.ks.modal.queue.DLXMessage;
  10. /**
  11. *
  12. * @author victor
  13. * @desc 死信接收处理消费者
  14. */
  15. @Component
  16. @RabbitListener(queues = MQConstant.DEFAULT_REPEAT_TRADE_QUEUE_NAME)
  17. public class TradeProcessor {
  18. @Autowired
  19. private IMessageQueueService messageQueueService;
  20. @RabbitHandler
  21. public void process(String content) {
  22. DLXMessage message = JSONUtils.toBean(content, DLXMessage.class);
  23. messageQueueService.send(message.getQueueName(), message.getContent());
  24. }
  25. }

启动项目之后,管理界面如下:

测试代码片段:

[java] view plain copy

 
    1. messageQueueService.send(MQConstant.HELLO_QUEUE_NAME,"测试延迟发送消息",60000);

spring boot Rabbitmq集成,延时消息队列实现的更多相关文章

  1. Sping Boot入门到实战之实战篇(一):实现自定义Spring Boot Starter——阿里云消息队列服务Starter

    在 Sping Boot入门到实战之入门篇(四):Spring Boot自动化配置 这篇中,我们知道Spring Boot自动化配置的实现,主要由如下几部分完成: @EnableAutoConfigu ...

  2. Spring Boot RabbitMQ 延迟消息实现完整版

    概述 曾经去网易面试的时候,面试官问了我一个问题,说 下完订单后,如果用户未支付,需要取消订单,可以怎么做 我当时的回答是,用定时任务扫描DB表即可.面试官不是很满意,提出: 用定时任务无法做到准实时 ...

  3. 从头开始搭建一个Spring boot+RabbitMQ环境

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  4. Spring boot+RabbitMQ环境

    Spring boot+RabbitMQ环境 消息队列在目前分布式系统下具备非常重要的地位,如下的场景是比较适合消息队列的: 跨系统的调用,异步性质的调用最佳. 高并发问题,利用队列串行特点. 订阅模 ...

  5. SpringBoot集成ActiveMq消息队列实现即时和延迟处理

    原文链接:https://blog.csdn.net/My_harbor/article/details/81328727 一.安装ActiveMq 具体安装步骤:自己谷歌去 二.新建springbo ...

  6. RabbitMQ实现延时消息的两种方法

    目录 RabbitMQ实现延时消息的两种方法 1.死信队列 1.1消息什么时候变为死信(dead-letter) 1.2死信队列的原理 1.3 代码实现 1.4死信队列的一个小坑 2 .延时插件 2. ...

  7. spring boot 2 集成JWT实现api接口认证

    JSON Web Token(JWT)是目前流行的跨域身份验证解决方案.官网:https://jwt.io/本文使用spring boot 2 集成JWT实现api接口验证. 一.JWT的数据结构 J ...

  8. RabbitMQ AMQP (高级消息队列协议)

    目录 RabbitMQ AMQP (高级消息队列协议) Message Queue 简介 概念 基本组成 场景及作用 AMQP简介 模型架构 基础组件 AMQP-RabbitMQ 简介 模型 特性 参 ...

  9. 第二百九十二节,RabbitMQ多设备消息队列-Python开发

    RabbitMQ多设备消息队列-Python开发 首先安装Python开发连接RabbitMQ的API,pika模块 pika模块为第三方模块  对于RabbitMQ来说,生产和消费不再针对内存里的一 ...

随机推荐

  1. HBase MemStore与HStoreFile 的大小分析

    Sumary: MemStore结构 KeyValue构成细节 HFile分析 Maven 项目例子使用了Maven来管理Dependency,要运行例子,需要有maven环境,后面提到的HFile, ...

  2. c# 实现遍历 DataTable 和DataSet (简单的方式)

    今天 做一个小程序 ,遇到了这样一个 问题就是 怎样简单的 遍历一个 DataTable 一. DataTable table= DBhelper.GetDataTable(str);foreach( ...

  3. XML简单学习

    XML简单概述 1.Extensible Markup language可扩展标记语言; 2.作用:具有层次性的描述有关系的数据: 体现在:描述数据关系:软件配置,以描述程序模块之间的关系: 语法介绍 ...

  4. DMSFrame 之查询表达式用法(一)

    where条件 WhereClip<Adm_User> where = new WhereClip<Adm_User>(q => q.DeleteFlag == fals ...

  5. greenplum全量恢复gprecoverseg -F出现Unable to connect to database时的相关分析及解决方法

    之前有两位朋友碰到过在对greenplum的系统构架更改后,出现全量恢复gprecoverseg -F也无法正常执行的情况. 报错信息为Unable to connect to database. R ...

  6. Chem 3D软件可以改变背景吗

    化学绘图过程中常常需要绘制三维结构的图形,Chem 3D软件是ChemOffice套件中专门用于绘制三维结构的组件.用过它的用户会发现,其背景颜色通常都默认为深蓝色,但是不是每个场景都适合用深蓝色的背 ...

  7. 清空select下拉框的方法

    $("#search").find("option").remove(); //或者 $("#search").empty();

  8. 72、android状态栏一体化,状态栏改变颜色

         只能在4.4以上版本使用. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q ...

  9. 将坐标转化为与X轴正半轴夹角模板

    //还需加PI 和 mabs 函数 double chg(double x,double y) { double tmps; )<1e-) { ) tmps=90.0; else tmps=27 ...

  10. Delphi xe---FIREDAC

    delphi  xe 10.2 完成FireDAC支持NoSQL MongoDB数据库,包括新FireDAC MongoDB,包括新FireDAC MongoDB的驱动.