# RocketMQ 实战:模拟电商网站场景综合案例(九)

news2024/12/23 5:03:40

RocketMQ 实战:模拟电商网站场景综合案例(九)

一、RocketMQ 实战:模拟电商网站场景综合案例-- 回退优惠券

1、回退优惠券


@Slf4j
@Component
@RocketMQMessageListener(topic = "${mq.order.topic}",consumerGroup = "${mq.order.consumer.group.name}",messageModel = MessageModel.BROADCASTING )
public class CancelMQListener implements RocketMQListener<MessageExt>{

    @Autowired
    private TradeCouponMapper couponMapper;

    @Override
    public void onMessage(MessageExt message) {

        try {
            //1. 解析消息内容
            String body = new String(message.getBody(), "UTF-8");
            MQEntity mqEntity = JSON.parseObject(body, MQEntity.class);
            log.info("接收到消息");
            //2. 查询优惠券信息
            TradeCoupon coupon = couponMapper.selectByPrimaryKey(mqEntity.getCouponId());
            //3.更改优惠券状态
            coupon.setUsedTime(null);
            coupon.setIsUsed(ShopCode.SHOP_COUPON_UNUSED.getCode());
            coupon.setOrderId(null);
            couponMapper.updateByPrimaryKey(coupon);
            log.info("回退优惠券成功");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("回退优惠券失败");
        }
    }
}

2、在 shop-coupon-service 工程模块中,完成 消费消息的 监听类 CancelMQListener.java 代码实现。


/**
 *   shop\shop-coupon-service\src\main\java\com\itheima\shop\mq\CancelMQListener.java
 *
 *   2024-6-11 创建 消费消息的 监听类 CancelMQListener.java
 */
package com.itheima.shop.mq;

import com.alibaba.fastjson.JSON;
import com.itheima.constant.ShopCode;
import com.itheima.entity.MQEntity;
import com.itheima.shop.mapper.TradeCouponMapper;
import com.itheima.shop.pojo.TradeCoupon;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;

@Slf4j
@Component
@RocketMQMessageListener(topic = "${mq.order.topic}", consumerGroup = "${mq.order.consumer.group.name}", messageModel = MessageModel.BROADCASTING)
public class CancelMQListener implements RocketMQListener<MessageExt> {

    @Autowired
    private TradeCouponMapper couponMapper;

    @Override
    public void onMessage(MessageExt message) {

        try {
            //1. 解析消息内容
            String body = new String(message.getBody(), "UTF-8");
            MQEntity mqEntity = JSON.parseObject(body, MQEntity.class);
            log.info("接收到消息");
            if(mqEntity.getCouponId()!=null){
                //2. 查询优惠券信息
                TradeCoupon coupon = couponMapper.selectByPrimaryKey(mqEntity.getCouponId());
                //3.更改优惠券状态
                coupon.setUsedTime(null);
                coupon.setIsUsed(ShopCode.SHOP_COUPON_UNUSED.getCode());
                coupon.setOrderId(null);
                couponMapper.updateByPrimaryKey(coupon);
            }
            log.info("回退优惠券成功");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("回退优惠券失败");
        }
    }
}

二、RocketMQ 实战:模拟电商网站场景综合案例-- 回退用户余额

1、回退用户余额


@Slf4j
@Component
@RocketMQMessageListener(topic = "${mq.order.topic}",consumerGroup = "${mq.order.consumer.group.name}",messageModel = MessageModel.BROADCASTING )
public class CancelMQListener implements RocketMQListener<MessageExt>{

    @Autowired
    private IUserService userService;

    @Override
    public void onMessage(MessageExt messageExt) {

        try {
            //1.解析消息
            String body = new String(messageExt.getBody(), "UTF-8");
            MQEntity mqEntity = JSON.parseObject(body, MQEntity.class);
            log.info("接收到消息");
            if(mqEntity.getUserMoney()!=null && mqEntity.getUserMoney().compareTo(BigDecimal.ZERO)>0){
                //2.调用业务层,进行余额修改
                TradeUserMoneyLog userMoneyLog = new TradeUserMoneyLog();
                userMoneyLog.setUseMoney(mqEntity.getUserMoney());
                userMoneyLog.setMoneyLogType(ShopCode.SHOP_USER_MONEY_REFUND.getCode());
                userMoneyLog.setUserId(mqEntity.getUserId());
                userMoneyLog.setOrderId(mqEntity.getOrderId());
                userService.updateMoneyPaid(userMoneyLog);
                log.info("余额回退成功");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("余额回退失败");
        }
    }
}

2、在 shop-user-service 工程模块中,完成 消费消息的 监听类 CancelMQListener.java 代码实现。


/**
 *   shop\shop-user-service\src\main\java\com\itheima\shop\mq\CancelMQListener.java
 *
 *   2024-6-11 创建 消费消息的 监听类 CancelMQListener.java
 */
package com.itheima.shop.mq;

import com.alibaba.fastjson.JSON;
import com.itheima.api.IUserService;
import com.itheima.constant.ShopCode;
import com.itheima.entity.MQEntity;
import com.itheima.shop.pojo.TradeUserMoneyLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;

@Slf4j
@Component
@RocketMQMessageListener(topic = "${mq.order.topic}",consumerGroup = "${mq.order.consumer.group.name}",messageModel = MessageModel.BROADCASTING )
public class CancelMQListener implements RocketMQListener<MessageExt>{

    @Autowired
    private IUserService userService;

    @Override  //用户余额回退
    public void onMessage(MessageExt messageExt) {

        try {
            //1.解析消息
            String body = new String(messageExt.getBody(), "UTF-8");
            MQEntity mqEntity = JSON.parseObject(body, MQEntity.class);
            log.info("接收到消息");
            if(mqEntity.getUserMoney()!=null && mqEntity.getUserMoney().compareTo(BigDecimal.ZERO)>0){
                //2.调用业务层,进行余额修改
                TradeUserMoneyLog userMoneyLog = new TradeUserMoneyLog();
                userMoneyLog.setUseMoney(mqEntity.getUserMoney());
                userMoneyLog.setMoneyLogType(ShopCode.SHOP_USER_MONEY_REFUND.getCode());
                userMoneyLog.setUserId(mqEntity.getUserId());
                userMoneyLog.setOrderId(mqEntity.getOrderId());
                userService.updateMoneyPaid(userMoneyLog);
                log.info("余额回退成功");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("余额回退失败");
        }
    }
}

三、RocketMQ 实战:模拟电商网站场景综合案例-- 取消订单

1、取消订单


@Override
    public void onMessage(MessageExt messageExt) {
        String body = new String(messageExt.getBody(), "UTF-8");
        String msgId = messageExt.getMsgId();
        String tags = messageExt.getTags();
        String keys = messageExt.getKeys();
        log.info("CancelOrderProcessor receive message:"+messageExt);
        CancelOrderMQ cancelOrderMQ = JSON.parseObject(body, CancelOrderMQ.class);
        TradeOrder order = orderService.findOne(cancelOrderMQ.getOrderId());
		order.setOrderStatus(ShopCode.SHOP_ORDER_CANCEL.getCode());
        orderService.changeOrderStatus(order);
        log.info("订单:["+order.getOrderId()+"]状态设置为取消");
        return order;
    }

2、在 shop-order-service 工程模块中,完成 消费消息的 监听类 CancelMQListener.java 代码实现。


/**
 *   shop\shop-order-service\src\main\java\com\itheima\shop\mq\CancelMQListener.java
 *
 *   2024-6-11 创建 消费消息的 监听类 CancelMQListener.java
 */
package com.itheima.shop.mq;

import com.alibaba.fastjson.JSON;
import com.itheima.constant.ShopCode;
import com.itheima.entity.MQEntity;
import com.itheima.shop.mapper.TradeOrderMapper;
import com.itheima.shop.pojo.TradeOrder;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;

@Slf4j
@Component
@RocketMQMessageListener(topic = "${mq.order.topic}",consumerGroup = "${mq.order.consumer.group.name}",messageModel = MessageModel.BROADCASTING )
public class CancelMQListener implements RocketMQListener<MessageExt>{

    @Autowired
    private TradeOrderMapper orderMapper;

    @Override  //取消订单
    public void onMessage(MessageExt messageExt) {

        try {
            //1. 解析消息内容
            String body = new String(messageExt.getBody(),"UTF-8");
            MQEntity mqEntity = JSON.parseObject(body, MQEntity.class);
            log.info("接受消息成功");
            //2. 查询订单
            TradeOrder order = orderMapper.selectByPrimaryKey(mqEntity.getOrderId());
            //3.更新订单状态为取消
            order.setOrderStatus(ShopCode.SHOP_ORDER_CANCEL.getCode());
            orderMapper.updateByPrimaryKey(order);
            log.info("订单状态设置为取消");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.info("订单取消失败");
        }
    }
}

四、RocketMQ 实战:模拟电商网站场景综合案例-- 失败补偿机制测试

1 、测试流程

1)准备测试环境

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ShopOrderServiceApplication.class)
public class OrderTest {

    @Autowired
    private IOrderService orderService;
}
2)准备测试数据
  • 用户数据
  • 商品数据
  • 优惠券数据
3)测试下单成功流程

@Test    
public void add(){
    Long goodsId=XXXL;
    Long userId=XXXL;
    Long couponId=XXXL;

    TradeOrder order = new TradeOrder();
    order.setGoodsId(goodsId);
    order.setUserId(userId);
    order.setGoodsNumber(1);
    order.setAddress("北京");
    order.setGoodsPrice(new BigDecimal("5000"));
    order.setOrderAmount(new BigDecimal("5000"));
    order.setMoneyPaid(new BigDecimal("100"));
    order.setCouponId(couponId);
    order.setShippingFee(new BigDecimal(0));
    orderService.confirmOrder(order);
}

执行完毕后,查看数据库中用户的余额、优惠券数据,及订单的状态数据

4)测试下单失败流程

代码同上。

执行完毕后,查看用户的余额、优惠券数据是否发生更改,订单的状态是否为取消。

2、删除数据库中使用日志表 和 记录表 内容,即 删除以下数据表内容。

trade_goods_number_log
trade_mq_consumer_log
trade_order
trade_user_money_log

3、保证 数据库中,用户 商品 优惠券 数据。

trade_user 表中,有数据,如余额是 1000 。
trade_order 表中,无数据。
trade_conpon 表中,优惠券 状态为 0 可用,优惠券 20 。

4、在 shop-order-service 工程模块中,创建 测试类 OrderServiceTest.java


/**
 *   shop\shop-order-service\src\test\java\com\itheima\test\OrderServiceTest.java
 *
 *   2024-6-11 创建 测试类 OrderServiceTest.java
 */
package com.itheima.test;

import com.itheima.api.IOrderService;
import com.itheima.shop.OrderServiceApplication;
import com.itheima.shop.pojo.TradeOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;
import java.math.BigDecimal;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = OrderServiceApplication.class)
public class OrderServiceTest {

    @Autowired
    private IOrderService orderService;

    @Test
    public void confirmOrder() throws IOException {

        Long coupouId = 345988230098857984L;
        Long goodsId = 345959443973935104L;
        Long userId = 345963634385633280L;

        TradeOrder order = new TradeOrder();
        order.setGoodsId(goodsId);
        order.setUserId(userId);
        order.setCouponId(coupouId);
        order.setAddress("北京");
        order.setGoodsNumber(1);
        order.setGoodsPrice(new BigDecimal(1000));
        order.setShippingFee(BigDecimal.ZERO);
        order.setOrderAmount(new BigDecimal(1000));
        order.setMoneyPaid(new BigDecimal(100));
        orderService.confirmOrder(order);

        System.in.read();
    }
}

5、启动测试类,查看数据库变化 和 idea 日志输出。

# RocketMQ 实战:模拟电商网站场景综合案例(八)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1814891.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

178.二叉树:最大二叉树(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* Tre…

Spring AI 大模型返回内容格式化源码分析及简单使用

为什么需要格式化输出 对于依赖可靠解析输出值的下游应用程序来说&#xff0c;生成结构化输出是LLMs非常重要的能力。开发人员希望快速将 AI 模型的结果转换为数据类型&#xff0c;例如 JSON、XML 或 Java 类&#xff0c;这些数据类型可以传递给其他应用程序函数和方法。 特别…

【数据分享】中国价格统计年鉴(2013-2022)

大家好&#xff01;今天我要向大家介绍一份重要的中国价格统计数据资源——《中国价格统计年鉴》。这份年鉴涵盖了从2013年到2022年中国价格统计全面数据&#xff0c;并提供限时免费下载。&#xff08;无需分享朋友圈即可获取&#xff09; 数据介绍 在过去的十年里&#xff0…

解决While loop问题 - Python

当我们在使用 while 循环时&#xff0c;需要确保循环的终止条件最终会被满足&#xff0c;否则循环将会无限执行下去。通常情况下&#xff0c;我们可以在循环内部修改循环控制变量&#xff0c;使得终止条件得以满足。 1、问题背景 一位开发者在使用 Python 开发一个基于文本的游…

NI USB-6009 DAQ采集卡拆解

所需设备&#xff1a; 1、NI USB-6009采集卡&#xff1b; 2、逻辑分析仪&#xff1b; NI USB-6009采集卡全貌&#xff1a; 性能参数&#xff1a; 内部照片&#xff1a; ADC芯片指标&#xff1a; 接线图&#xff1a; 差分模式采样&#xff1a; 采集过程中的SPI总线数据监控&a…

Laravel 6 - 第十九章 模型文件

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

不谈AI能替代什么,就聊能帮我们干活的AI客服机器人!

最近在直播群里有老板在找客服外包&#xff0c;因为客服压力大&#xff0c;接不过来了&#xff0c;想找找外包支援一下。据了解电商客服除了压力大&#xff0c;还会遇到过量的重复劳动&#xff0c;比如我们问一个产品&#xff0c;同一天可能就有几百上千客户问同样的问题&#…

如何把视频的声音转换成音频?干货分享

在数字时代&#xff0c;我们常常需要处理视频文件&#xff0c;而有时候我们只对视频中的音频部分感兴趣。无论是提取影片中的音乐、制作声音效果&#xff0c;还是其他音频处理需求&#xff0c;将视频的声音转换成音频是一个常见而有用的技能。如何把视频的声音转换成音频&#…

css实现优惠券样式

实现优惠券效果&#xff1a; 实现思路&#xff1a; 需要三个盒子元素&#xff0c;使用 css 剪裁&#xff0c;利用 ellipse 属性&#xff0c;将两个盒子分别裁剪成两个半圆&#xff0c;位置固定在另一个盒子元素左右两边适当位置上。为另一个盒子设置想要的样式&#xff0c;圆角…

Tailwind CSS 实战指南:快速构建响应式网页设计

title: Tailwind CSS 实战指南&#xff1a;快速构建响应式网页设计 date: 2024/6/12 updated: 2024/6/12 author: cmdragon excerpt: 这篇文章介绍了Tailwind CSS框架的特点与优势&#xff0c;包括其作为实用性的CSS框架如何通过预设的样式类实现快速布局和设计&#xff0c;…

jeecgboot右上角用户重置密码权限按钮配置不生效问题解决

选了菜单权限用户重置密码权限按钮还是不生效&#xff0c;使用这个缓存读取的是下述redis文件中&#xff0c;用户退出了账户&#xff0c;重新登陆也只会刷新token但是并不会刷新这这个配置&#xff0c;所以需要手动清除redis缓存。 这个问题我也是看了很久才发现&#xff0c;如…

新能源车用驱动器 电机电驱

硕博电子的电机电驱是以一体化动力总成为设计理念&#xff0c;整合电控、电机核心模块&#xff0c;推出的电机电控一体化动力总成。电机电控动力总成采用矢量控制算法和CAN总线通信技术&#xff0c;体积小、效率高、免维护、电磁兼容性强、方便调试&#xff0c;提高了系统的可靠…

【源码】16国语言交易所源码/币币交易+期权交易+秒合约交易+永续合约+交割合约+新币申购+投资理财/手机端uniapp纯源码+PC纯源码+后端PHP

测试环境&#xff1a;Linux系统CentOS7.6、宝塔面板、Nginx、PHP7.3、MySQL5.6&#xff0c;根目录public&#xff0c;伪静态laravel5&#xff0c;开启ssl证书 语言&#xff1a;16种&#xff0c;看图 这套带前端uniapp纯源码&#xff0c;手机端和pc端都有纯源码&#xff0c;后…

指定cuda版本的torch包安装

文章目录 1.查看自己电脑的cuda版本2.确定安装torch的conda指令2.1进入网站[cuda对应的torch版本](https://pytorch.org/get-started/previous-versions/) 3.检验torch的cuda版本是否可用 1.查看自己电脑的cuda版本 winr输入cmd回车进行电脑终端界面 输入nvidia-smi指令 nvid…

【CT】LeetCode手撕—53. 最大子数组和

目录 题目1-思路2- 实现⭐53. 最大子数组和——题解思路 3- ACM 实现 题目 原题连接&#xff1a;53. 最大子数组和 1-思路 动规五部曲 1. 定义 dp 数组 dp[i] 含义为&#xff1a;下标为 i 的数组的最大子数组和 2. 递推公式 因为所求的是最大子数组的和&#xff0c;即当前 n…

转型AI产品经理(8):“习惯形成模型”如何应用在Chatbot产品中

习惯形成模型是心理学中用来解释习惯如何产生、发展以及如何被改变的理论框架。它通常包含以下几个关键阶段&#xff1a; 1. 触发 习惯循环的开始是一个触发因素&#xff0c;它可以是外部的&#xff08;如时间、地点、情绪状态、特定的人或物&#xff09;或内部的&#xff08…

红海云入选《2024中国数据智能产业图谱1.0》

近日&#xff0c;国内知名大数据产业创新服务媒体数据猿携手上海大数据联盟重磅发布了《2024中国数据智能产业图谱1.0》。红海云凭借在人力资源数字化应用领域的卓越产品创新与服务&#xff0c;成功入选图谱「 企业应用-人力资源」板块。 《2024中国数据智能产业图谱1.0》由数…

深度学习(一)——使用Python读取图片

一、Python学习两大道具 1. dir()工具 作用&#xff1a;支持打开package&#xff0c;看到里面的工具函数 示例&#xff1a; (1) 输出torch库包含的函数 dir(torch)(2) 输出torch.AVG函数中的参数 dir(torch.AVG)2. help()工具 作用&#xff1a;说明书&#xff0c;查看库中…

代码随想录算法训练营第35天|● 1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果

K次取反后最大化的数组 1005. K 次取反后最大化的数组和 - 力扣&#xff08;LeetCode&#xff09; 本题首先想到尽可能将负的数变成正数&#xff0c;这样才能得到最大和,将数组进行按绝对值大小进行降序排序&#xff0c;若遇到负数将其取反后k--&#xff0c;若后面大于0 &…

7.枚举和模式匹配

一、enum枚举 1.1 定义枚举类型和对应的数据 //定义枚举 #[derive(Debug)] enum IpAddrKind{IPv4,IPv6, }struct Ipaddr{kind: IpAddrKind, //设置kind为IpAddrKind的枚举类型address: String, }fn route(ip_addr: &Ipaddr){println!("ip_type {:#?}", ip_a…