商城项目(七)整合RabbitMQ实现延迟消息

本文主要整合RabbitMQ实现延迟消息的过程,以发送延迟消息取消超时订单为例。

环境配置

RabbitMQ

RabbitMQ是一个被广泛使用的开源消息队列。它是轻量级且易于部署的,它能支持多种消息协议。RabbitMQ可以部署在分布式和联合配置中,以满足高规模、高可用性的需求。

  1. 安装Erlang,下载地址:http://erlang.org/download/otp_win64_21.3.exe
  2. 安装RabbitMQ,下载地址:https://dl.bintray.com/rabbitmq/all/rabbitmq-server/3.7.14/rabbitmq-server-3.7.14.exe
  3. 安装完成后,进入RabbitMQ安装目录下的sbin目录
  4. 在地址栏输入cmd并回车启动命令行,然后输入以下命令启动管理功能:
  5. 访问地址查看是否安装成功:http://localhost:15672/
  6. 访问地址查看是否安装成功:http://localhost:15672/
  7. 创建帐号并设置其角色为管理员:mall mall
  8. 创建一个新的虚拟host为:/mall
  9. 点击mall用户进入用户配置页面
  10. 给mall用户配置该虚拟host的权限
  11. 至此,RabbitMQ的安装和配置完成。

RabbitMQ的消息模型


Lombok

Lombok为Java语言添加了非常有趣的附加功能,你可以不用再为实体类手写getter,setter等方法,通过一个注解即可拥有。

注意:需要安装idea的Lombok插件,并在项目中的pom文件中添加依赖。

业务场景说明

用于解决用户下单以后,订单超时如何取消订单的问题。

  • 用户进行下单操作(会有锁定商品库存、使用优惠券、积分一系列的操作);
  • 生成订单,获取订单的id;
  • 获取到设置的订单超时时间(假设设置的为60分钟不支付取消订单);
  • 按订单超时时间发送一个延迟消息给RabbitMQ,让它在订单超时后触发取消订单的操作;
  • 如果用户没有支付,进行取消订单操作(释放锁定商品库存、返还优惠券、返回积分一系列操作)。

整合RabbitMQ实现延迟消息

在pom.xml中添加相关依赖

<!--消息队列相关依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--lombok依赖-->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency>

修改SpringBoot配置文件

修改application.yml文件,在spring节点下添加RabbitMQ相关配置。

  rabbitmq:host: localhost # rabbitmq的连接地址port: 5672 # rabbitmq的连接端口号virtual-host: /mall # rabbitmq的虚拟hostusername: mall # rabbitmq的用户名password: mall # rabbitmq的密码publisher-confirms: true #如果对异步消息需要回调必须设置为true

添加消息队列的枚举配置类QueueEnum

用于延迟消息队列及处理取消订单消息队列的常量定义,包括交换机名称、队列名称、路由键名称。

/*** 消息队列枚举配置*/
@Getter
public enum QueueEnum {/*** 消息通知队列*/QUEUE_ORDER_CANCEL("mall.order.direct", "mall.order.cancel", "mall.order.cancel"),/*** 消息通知ttl队列*/QUEUE_TTL_ORDER_CANCEL("mall.order.direct.ttl", "mall.order.cancel.ttl", "mall.order.cancel.ttl");/*** 交换名称*/private String exchange;/*** 队列名称*/private String name;/*** 路由键*/private String routeKey;QueueEnum(String exchange, String name, String routeKey) {this.exchange = exchange;this.name = name;this.routeKey = routeKey;}
}

添加RabbitMQ的配置

用于配置交换机、队列及队列与交换机的绑定关系。

/*** 消息队列配置*/
@Configuration
public class RabbitMqConfig {/*** 订单消息实际消费队列所绑定的交换机*/@BeanDirectExchange orderDirect() {return (DirectExchange) ExchangeBuilder.directExchange(QueueEnum.QUEUE_ORDER_CANCEL.getExchange()).durable(true).build();}/*** 订单延迟队列队列所绑定的交换机*/@BeanDirectExchange orderTtlDirect() {return (DirectExchange) ExchangeBuilder.directExchange(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getExchange()).durable(true).build();}/*** 订单实际消费队列*/@Beanpublic Queue orderQueue() {return new Queue(QueueEnum.QUEUE_ORDER_CANCEL.getName());}/*** 订单延迟队列(死信队列)*/@Beanpublic Queue orderTtlQueue() {return QueueBuilder.durable(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getName()).withArgument("x-dead-letter-exchange", QueueEnum.QUEUE_ORDER_CANCEL.getExchange())//到期后转发的交换机.withArgument("x-dead-letter-routing-key", QueueEnum.QUEUE_ORDER_CANCEL.getRouteKey())//到期后转发的路由键.build();}/*** 将订单队列绑定到交换机*/@BeanBinding orderBinding(DirectExchange orderDirect,Queue orderQueue){return BindingBuilder.bind(orderQueue).to(orderDirect).with(QueueEnum.QUEUE_ORDER_CANCEL.getRouteKey());}/*** 将订单延迟队列绑定到交换机*/@BeanBinding orderTtlBinding(DirectExchange orderTtlDirect,Queue orderTtlQueue){return BindingBuilder.bind(orderTtlQueue).to(orderTtlDirect).with(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getRouteKey());}}

在RabbitMQ管理页面可以看到以下交换机和队列


交换机及队列说明

  • mall.order.direct(取消订单消息队列所绑定的交换机):绑定的队列为mall.order.cancel,一旦有消息以mall.order.cancel为路由键发过来,会发送到此队列。
  • mall.order.direct.ttl(订单延迟消息队列所绑定的交换机):绑定的队列为mall.order.cancel.ttl,一旦有消息以mall.order.cancel.ttl为路由键发送过来,会转发到此队列,并在此队列保存一定时间,等到超时后会自动将消息发送到mall.order.cancel(取消订单消息消费队列)。

添加延迟消息的发送者CancelOrderSender

用于向订单延迟消息队列(mall.order.cancel.ttl)里发送消息。

/*** 取消订单消息的发出者*/
@Component
public class CancelOrderSender {private static Logger LOGGER =LoggerFactory.getLogger(CancelOrderSender.class);@Autowiredprivate AmqpTemplate amqpTemplate;public void sendMessage(Long orderId,final long delayTimes){//给延迟队列发送消息amqpTemplate.convertAndSend(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getExchange(), QueueEnum.QUEUE_TTL_ORDER_CANCEL.getRouteKey(), orderId, new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) throws AmqpException {//给消息设置延迟毫秒值message.getMessageProperties().setExpiration(String.valueOf(delayTimes));return message;}});LOGGER.info("send delay message orderId:{}",orderId);}
}

添加取消订单消息的接收者CancelOrderReceiver

用于从取消订单的消息队列(mall.order.cancel)里接收消息。

/*** 取消订单消息的处理者*/
@Component
@RabbitListener(queues = "mall.order.cancel")
public class CancelOrderReceiver {private static Logger LOGGER =LoggerFactory.getLogger(CancelOrderReceiver.class);@Autowiredprivate OmsPortalOrderService portalOrderService;@RabbitHandlerpublic void handle(Long orderId){LOGGER.info("receive delay message orderId:{}",orderId);portalOrderService.cancelOrder(orderId);}
}

添加OmsPortalOrderService接口

/*** 前台订单管理Service*/
public interface OmsPortalOrderService {/*** 根据提交信息生成订单*/@TransactionalCommonResult generateOrder(OrderParam orderParam);/*** 取消单个超时订单*/@Transactionalvoid cancelOrder(Long orderId);
}

添加OmsPortalOrderService的实现类OmsPortalOrderServiceImpl

/*** 前台订单管理Service*/
@Service
public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {private static Logger LOGGER = LoggerFactory.getLogger(OmsPortalOrderServiceImpl.class);@Autowiredprivate CancelOrderSender cancelOrderSender;@Overridepublic CommonResult generateOrder(OrderParam orderParam) {//todo 执行一系类下单操作,具体参考mall项目LOGGER.info("process generateOrder");//下单完成后开启一个延迟消息,用于当用户没有付款时取消订单(orderId应该在下单后生成)sendDelayMessageCancelOrder(11L);return CommonResult.success(null, "下单成功");}@Overridepublic void cancelOrder(Long orderId) {//todo 执行一系类取消订单操作,具体参考mall项目LOGGER.info("process cancelOrder orderId:{}",orderId);}private void sendDelayMessageCancelOrder(Long orderId) {//获取订单超时时间,假设为60分钟long delayTimes = 30 * 1000;//发送延迟消息cancelOrderSender.sendMessage(orderId, delayTimes);}
}

添加OmsPortalOrderController定义接口

/*** 订单管理Controller*/
@Controller
@Api(tags = "OmsPortalOrderController", description = "订单管理")
@RequestMapping("/order")
public class OmsPortalOrderController {@Autowiredprivate OmsPortalOrderService portalOrderService;@ApiOperation("根据购物车信息生成订单")@RequestMapping(value = "/generateOrder", method = RequestMethod.POST)@ResponseBodypublic Object generateOrder(@RequestBody OrderParam orderParam) {return portalOrderService.generateOrder(orderParam);}
}

进行接口测试

调用下单接口

注意:已经将延迟消息时间设置为30秒

商城项目(七)整合RabbitMQ实现延迟消息相关推荐

  1. rabbitmq 取消消息_SpringBoot整合RabbitMQ实现延迟消息

    ## RabbitMQ RabbitMQ是一个被广泛使用的开源消息队列.它是轻量级且易于部署的,它能支持多种消息协议.RabbitMQ可以部署在分布式和联合配置中,以满足高规模.高可用性的需求. R ...

  2. mall整合RabbitMQ实现延迟消息

    摘要 本文主要讲解mall整合RabbitMQ实现延迟消息的过程,以发送延迟消息取消超时订单为例.RabbitMQ是一个被广泛使用的开源消息队列.它是轻量级且易于部署的,它能支持多种消息协议.Rabb ...

  3. RabbitMQ实现延迟消息

    本文主要讲解mall整合RabbitMQ实现延迟消息的过程,以发送延迟消息取消超时订单为例. 文章目录 项目使用框架介绍 RabbitMQ RabbitMQ的安装和使用 Lombok 业务场景说明 整 ...

  4. spring boot rabbitmq_Spring Boot+RabbitMQ 实现延迟消息实现完整版,实用!

    本文同步Java知音社区,专注于Java 作者:Sam哥哥http://blog.csdn.net/linsongbin1/article/details/80178122 概述 曾经去网易面试的时候 ...

  5. python美多商城项目百度网盘_美多商城项目(七)

    正文共: 7620字 4图 预计阅读时间: 20分钟 每日分享 If you can change your mind, you can change your life. 如果你愿意改变你的想法,你 ...

  6. java B2B2C 仿淘宝电子商城系统-基于Rabbitmq实现延迟消息

    预备知识 1.1 消息传递 首先我们知道消费者是从队列中获取消息的,那么消息是如何到达队列的? 当我们发送一条消息时,首先会发给交换器(exchange),交换器根据规则(路由键:routing ke ...

  7. (十五)java B2B2C 多级Springboot多租户电子商城系统 Springboot整合RabbitMQ

    Spring cloud b2b2c电子商务社交平台源码请加企鹅求求:一零三八七七四六二六.这篇文章带你了解怎么整合RabbitMQ服务器,并且通过它怎么去发送和接收消息.我将构建一个springbo ...

  8. 【Spring Boot】Spring Boot之整合RabbitMQ并实现消息的发送和接收

    一.项目配置 1)引入maven坐标 <!--amqp--><dependency><groupId>org.springframework.boot</gr ...

  9. SpringBoot整合RabbitMQ(六大消息模式、消息手动应答机制)

    目录 1.环境搭建 2.队列模式 3.发布订阅模式 4.路由模式 5.主题模式 6.消息手动应答机制 7.回调函数-确认机制(发布确认模式) 1.环境搭建 引入pom: <!-- rabbitM ...

最新文章

  1. Gut: 孕期健康对孩子至关重要!
  2. BTC引领市场多头情绪爆发 BCH筑底完成望成上涨新风口
  3. InnoDB 事务/锁/多版本分析?你了解多少?
  4. 2020年上半年美团夜宵指数发展报告
  5. leetcode - 416. 分割等和子集
  6. 计算机接口及应用技术,计算机接口技术及应用 第9讲 控制网络技术(2 现场总线).pdf...
  7. jmeter 登录用户并发压力测试案例_用jmeter进行多用户并发压力测试 [转]
  8. 发现新的预言梦种类:预言梦投射
  9. 随笔:读书笔记--《九败一胜:美团创始人王兴创业十年》
  10. 一寸照片像素是多少?教你一寸照片电子版怎么弄
  11. 轮询、长轮询、长连接、websocket
  12. ST-Link驱动的下载、安装、配置,以及ST-Link固件的升级
  13. 如何找到mysql的初始密码_如何查看mysql的初始密码
  14. php guzzlehttp,使用Guzzle执行HTTP请求
  15. 打雪仗java_【UER #8】打雪仗 - 题目 - Universal Online Judge
  16. C#面向对象编程:构造函数
  17. 1264. 动态求连续区间和
  18. 如何查看手机计算机历史记录,怎么查看电脑历史操作记录
  19. Linux:共享内存
  20. cmd中的循环语句for

热门文章

  1. java剪切_java---头像剪切功能
  2. 【场景化解决方案】“云上管车”连接货运系统,帮助企业高效调度车辆
  3. openmv可以c语言编程吗,OpenMV
  4. 信息技术服务标准(ITSS)系列培训 IT服务工程师/服务项目经理培训通知
  5. Linux/ubuntu18.04 撤销普通用户poweroff,halt,reboot权限
  6. 树莓派的入门配置,包括ftp 远程桌面,中问输入法,语音模块配置
  7. Qt设置软件启动动画(开屏动画、欢迎界面)
  8. 老年人晕倒的几种原因
  9. 什么是创业板股票?如何购买?
  10. 统计通话次数和时间的软件_通话时间统计软件-通话时间统计app下载 v2.3-都去下载...