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

文章目录

  • 项目使用框架介绍
    • RabbitMQ
      • RabbitMQ的安装和使用
    • Lombok
  • 业务场景说明
  • 整合RabbitMQ实现延迟消息
    • 在pom.xml中添加相关依赖
    • 修改SpringBoot配置文件
    • 添加消息队列的枚举配置类QueueEnum
    • 添加RabbitMQ的配置
      • 在RabbitMQ管理页面可以看到以下交换机和队列
      • 交换机及队列说明
    • 添加延迟消息的发送者CancelOrderSender
    • 添加取消订单消息的接收者CancelOrderReceiver
    • 添加OmsPortalOrderService接口
    • 添加OmsPortalOrderService的实现类OmsPortalOrderServiceImpl
    • 添加OmsPortalOrderController定义接口
  • 进行接口测试
    • 调用下单接口

项目使用框架介绍

RabbitMQ

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

RabbitMQ的安装和使用

注意:Erlang版本与RabbitMQ版本有对应关系,版本不对应会导致RabbitMQ安装不了

  1. 安装Erlang,下载地址:http://erlang.org/download/otp_win64_23.3.exe
  2. Erlang需要配置环境变量,配置bin目录所在路径
  3. 安装RabbitMQ,下载地址:https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.16/rabbitmq-server-3.8.16.exe
  4. 安装完成后,进入RabbitMQ安装目录下的sbin目录
  5. 在地址栏输入cmd并回车启动命令行,然后输入以下命令启动管理功能:
rabbitmq-plugins enable rabbitmq_management

如果出现:

解决方法:
将 C:\Users\Administrator.erlang.cookie 同步至C:\Windows\System32\config\systemprofile.erlang.cookie
同时删除:C:\Users\Administrator\AppData\Roaming\RabbitMQ目录
输入命令:rabbitmq-plugins.bat enable rabbitmq_management ,出现下面信息表示插件安装成功:

输入命令:rabbitmq-server.bat

  1. 访问地址查看是否启动成功:http://localhost:15672/
  2. 输入账号密码并登录:guest guest
  3. 创建帐号并设置其角色为管理员:mall mall
  4. 创建一个新的虚拟host为:/mall
  5. 点击mall用户进入用户配置页面
  6. 给mall用户配置该虚拟host的权限
  7. 至此,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

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

package com.macro.mall.tiny.dto;import lombok.Getter;/*** 消息队列枚举配置* Created by macro on 2018/9/14.*/@Getterpublic 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的配置

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

package com.macro.mall.tiny.config;import com.macro.mall.tiny.dto.QueueEnum;import org.springframework.amqp.core.*;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/*** 消息队列配置* Created by macro on 2018/9/14.*/@Configurationpublic 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)里发送消息。

package com.macro.mall.tiny.component;import com.macro.mall.tiny.dto.QueueEnum;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.amqp.AmqpException;import org.springframework.amqp.core.AmqpTemplate;import org.springframework.amqp.core.Message;import org.springframework.amqp.core.MessagePostProcessor;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;/*** 取消订单消息的发出者* Created by macro on 2018/9/14.*/@Componentpublic 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)里接收消息。

package com.macro.mall.tiny.component;import com.macro.mall.tiny.service.OmsPortalOrderService;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.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;/*** 取消订单消息的处理者* Created by macro on 2018/9/14.*/@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接口

package com.macro.mall.tiny.service;import com.macro.mall.tiny.common.api.CommonResult;import com.macro.mall.tiny.dto.OrderParam;import org.springframework.transaction.annotation.Transactional;/*** 前台订单管理Service* Created by macro on 2018/8/30.*/public interface OmsPortalOrderService {/*** 根据提交信息生成订单*/@TransactionalCommonResult generateOrder(OrderParam orderParam);/*** 取消单个超时订单*/@Transactionalvoid cancelOrder(Long orderId);}

添加OmsPortalOrderService的实现类OmsPortalOrderServiceImpl

package com.macro.mall.tiny.service.impl;import com.macro.mall.tiny.common.api.CommonResult;import com.macro.mall.tiny.component.CancelOrderSender;import com.macro.mall.tiny.dto.OrderParam;import com.macro.mall.tiny.service.OmsPortalOrderService;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;/*** 前台订单管理Service* Created by macro on 2018/8/30.*/@Servicepublic 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定义接口

package com.macro.mall.tiny.controller;import com.macro.mall.tiny.dto.OrderParam;import com.macro.mall.tiny.service.OmsPortalOrderService;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;/*** 订单管理Controller* Created by macro on 2018/8/30.*/@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. spring boot rabbitmq_Spring Boot+RabbitMQ 实现延迟消息实现完整版,实用!

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

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

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

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

    商城项目(七)整合RabbitMQ实现延迟消息 本文主要整合RabbitMQ实现延迟消息的过程,以发送延迟消息取消超时订单为例. 环境配置 RabbitMQ RabbitMQ是一个被广泛使用的开源消息 ...

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

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

  6. RabbitMQ 延迟消息的极限是多少?

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 之前在写Spring Cloud Stream专题内容的时候,特地介绍了一下如何使用Rabb ...

  7. RabbitMQ延迟消息的极限是多少?

    之前在写Spring Cloud Stream专题内容的时候,特地介绍了一下如何使用RabbitMQ的延迟消息来实现定时任务.最近正好因为开发碰到了使用过程中发现,延迟消息没有效果,消息直接就被消费了 ...

  8. RabbitMQ延迟消息场景分析以及实现两种方式(SpringBoot)

    使用场景,不限于下面 用户下订单结束,如果用户未及时支付,后续需要取消订单,可以怎么做?定时任务可以做,但是不能接近实时或者消耗数据库性能太大. [数据库定时任务方案]:定时任务可以做到订单的状态的改 ...

  9. RabbitMQ (四)实现延迟消息

    1 概述 常用的延迟消息实现方式有: 利用 队列TTL + 死信队列 方式实现 利用消息延迟插件实现 消息变成死信的原因有:​​​​ 消息过期.消息TTL或队列TTL 消息被拒绝.消费者调用了 cha ...

最新文章

  1. 鞋企立足信息化建设 力争突破发展瓶颈
  2. Spring自动装配Beans
  3. ABAP SET UPDATE TASK LOCAL的测试
  4. 弄懂webpack,只要看这一片就够了(文末有福利)
  5. C# .Net 视频下载功能(本机文件)及转发下载功能(Http远程文件)
  6. 【转】C#中Invoke的用法
  7. mysql操作符_MySql 中的=操作符
  8. css-modules,CSS Modules 方案
  9. 深入探究Java中hashCode()和equals()的关系
  10. java引用型变量_java-有没有办法用类型变量引用当前类型?
  11. J2EE技术-Hibernate
  12. 微型计算机的地址加法器,地址加法器
  13. pwnable.kr第二遍---mistake
  14. java 判断日期格式_java判断字符是否是日期格式
  15. 电脑桌面计算机打开无响应,电脑任务栏假死点击没反应的解决方法(win7与xp)
  16. git常用操作--分支同步master 本地库提交到远程分支
  17. Linux(信号,进程间通信)共享内存,信号量,消息队列
  18. Dubbo之默认协议dubbo
  19. 自媒体初学者如何正确学习视频剪辑【视频制作自学成大神】?
  20. 数据库 之数据库设计浅知识 -- 设计概述、概念结构设计(E-R模型概述)、逻辑结构设计(函数依赖和范式)、物理结构设计

热门文章

  1. 游戏开挂的罪与非罪——从“王者荣耀外挂案”说起
  2. Android ANR问题总结
  3. 第1.3章:StarRocks部署--单机部署
  4. 微信小程序 MinUI 组件库系列之 abnor 异常流组件 1
  5. python项目管理工具_项目管理工具之Trac
  6. 【计算机原理与接口技术(UNIX)⑲ 完结篇】——可编程计数器 8254 [ 流光发生器、8254工作方式检测程序的设计]
  7. 让程序自动玩数独游戏让你秒变骨灰级数独玩家
  8. discuz当qq绑定超过5个网址时 如何解除绑定qq
  9. 6000字总结MySQL最基础的增删查改命令
  10. 2021年区域赛ICPC沈阳站J-Luggage Lock(代码简洁)