一,为什么要使用消息队列实现删除购物车商品功能?

消息队列主要用来处理不需要立刻返回结果的业务,

常见的例子:

用户在下单后,要清除原购物车中的商品,

这个处理过程不需要马上实现也不需要返回结果给用户,

所以就适合使用队列来实现

说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

对应的源码可以访问这里获取: https://github.com/liuhongdi/

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,演示项目的相关信息

1,项目地址

https://github.com/liuhongdi/mqcart

2,项目功能说明:

演示了用rocketmq实现消息的发送和接收

3, 项目结构:如图:

三,配置文件说明

1,send/pom.xml

        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.7.1</version>
</dependency>
<!--fastjson begin-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>

2,receive/pom.xml

        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.7.1</version>
</dependency>
<!--fastjson begin-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>

说明:两个模块的pom.xml内容相同

3,receive/application.properties

server.port=8081

说明:两个模块同时运行时,需要把端口区分开,
         send不做修改,使用默认的8080端口
         receive这里指定使用8081端口

四,java代码说明

1,send/HomeController.java

@RestController
@RequestMapping("/home")
public class HomeController {
@Autowired
private Producer producer;
//初始化并发送消息
@RequestMapping("/send")
public String send() throws Exception {
//要删除的购物车的id
List<Integer> cartList = new ArrayList<Integer>();
cartList.add(1);
cartList.add(2);
cartList.add(3);
//消息
CartMsg msg = new CartMsg();
msg.setUserId(1);
msg.setCartList(cartList); String msgJson = JSON.toJSONString(msg);
//生成一个信息,标签在这里手动指定
Message message = new Message(RocketConstants.TOPIC, "carttag", msgJson.getBytes());
//发送信息
SendResult sendResult = producer.getProducer().send(message);
System.out.println("生产者已发送一条信息,内容={"+sendResult+"}"); return "success";
}
}

2,send/CartMsg.java

//购物车消息
public class CartMsg {
//用户id
private int userId;
public int getUserId() {
return this.userId;
}
public void setUserId(int userId) {
this.userId = userId;
} //购物车id
private List<Integer> cartList;
public List<Integer> getCartList() {
return this.cartList;
}
public void setCartList(List<Integer> cartList) {
this.cartList = cartList;
}
}

发送的消息体,
两个模块中的的CartMsg.java文件相同

3,send/RocketConstants.java

public class RocketConstants {
//name server,有多个时用分号隔开
public static final String NAME_SERVER = "127.0.0.1:9876";
//topic的名字,应该从服务端先创建好,否则会报错
public static final String TOPIC = "laoliutest";
}

配置name server和topic,

两个模块中的的RocketConstants.java文件相同

4,send/Producer.java

//消息生产者类
@Component
public class Producer {
private String producerGroup = "cart_producer";
private DefaultMQProducer producer;
//构造
public Producer(){
//创建生产者
producer = new DefaultMQProducer(producerGroup);
//不开启vip通道
producer.setVipChannelEnabled(false);
//设定 name server
producer.setNamesrvAddr(RocketConstants.NAME_SERVER);
start();
} //使producer启动
public void start(){
try {
this.producer.start();
} catch (MQClientException e) {
e.printStackTrace();
}
}
//返回producer
public DefaultMQProducer getProducer(){
return this.producer;
} //进行关闭的方法
public void shutdown(){
this.producer.shutdown();
}
}

5,receive/Consumer.java

@Component
public class Consumer { //消费者实体对象
private DefaultMQPushConsumer consumer; //消费者组
public static final String CONSUMER_GROUP = "cart_consumer"; //构造函数 用来实例化对象
public Consumer() throws MQClientException {
consumer = new DefaultMQPushConsumer(CONSUMER_GROUP);
consumer.setNamesrvAddr(RocketConstants.NAME_SERVER);
//指定消费模式
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
//指定订阅主题
//指定订阅标签,*代表所有标签
consumer.subscribe(RocketConstants.TOPIC, "*");
//注册一个消费消息的Listener
//对消息的消费在这里实现
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
//遍历接收到的消息
try {
for (Message msg : msgs) {
//得到消息的body
String body = new String(msg.getBody(), "utf-8");
//用json转成对象
CartMsg msgOne = JSON.parseObject(body, CartMsg.class);
//打印用户id
System.out.println(msgOne.getUserId());
//打印消息内容
System.out.println("消费者已接收到消息-topic={"+msg.getTopic()+"}, 消息内空={"+body+"}");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
consumer.start();
System.out.println("消费者 启动成功=======");
}
}

这个是消息的消费者

6,其他消息的非关键代码可访问github

五,演示效果

1,访问send模块的controller:

http://127.0.0.1:8080/home/send

显示发送成功:

success

查看控制台:

生产者已发送一条信息,内容={SendResult [sendStatus=SEND_OK, msgId=C0A803D5113442A57993512ADA8E0000,
offsetMsgId=7F00000100002A9F0000000000003AE8, messageQueue=MessageQueue [topic=laoliutest, brokerName=broker-a, queueId=3], queueOffset=0]}

2,查看receive模块的控制台:

1
消费者已接收到消息-topic={laoliutest}, 消息内容={{"cartList":[1,2,3],"userId":1}

收到了消息,消息内容可解析

六,查看spring boot版本:

  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.3.RELEASE)

spring boot:用rocketmq消息订阅实现删除购物车商品功能(spring boot 2.3.3)的更多相关文章

  1. RocketMQ(消息重发、重复消费、事务、消息模式)

    分布式开放消息系统(RocketMQ)的原理与实践 RocketMQ基础:https://github.com/apache/rocketmq/tree/rocketmq-all-4.5.1/docs ...

  2. Spring cloud stream【消息分区】

      在上篇文章中我们给大家介绍了Stream的消息分组,可以实现消息的重复消费的问题,但在某些场景下分组还不能满足我们的需求,比如,同时有多条同一个用户的数据,发送过来,我们需要根据用户统计,但是消息 ...

  3. spring boot: 用redis的消息订阅功能更新应用内的caffeine本地缓存(spring boot 2.3.2)

    一,为什么要更新caffeine缓存? 1,caffeine缓存的优点和缺点 生产环境中,caffeine缓存是我们在应用中使用的本地缓存, 它的优势在于存在于应用内,访问速度最快,通常都不到1ms就 ...

  4. Spring Kafka和Spring Boot整合实现消息发送与消费简单案例

    本文主要分享下Spring Boot和Spring Kafka如何配置整合,实现发送和接收来自Spring Kafka的消息. 先前我已经分享了Kafka的基本介绍与集群环境搭建方法.关于Kafka的 ...

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

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

  6. Spring Cloud(十一)高可用的分布式配置中心 Spring Cloud Bus 消息总线集成(RabbitMQ)

    详见:https://www.w3cschool.cn/spring_cloud/spring_cloud-jl8a2ixp.html 上一篇文章,留了一个悬念,Config Client 实现配置的 ...

  7. SpringCloud之Spring Cloud Stream:消息驱动

    Spring Cloud Stream 是一个构建消息驱动微服务的框架,该框架在Spring Boot的基础上整合了Spring Integrationg来连接消息代理中间件(RabbitMQ, Ka ...

  8. RocketMQ 消息队列单机部署及使用

    转载请注明来源:http://blog.csdn.net/loongshawn/article/details/51086876 相关文章: <RocketMQ 消息队列单机部署及使用> ...

  9. RocketMQ消息模型

    rocketmq采用的是发布-订阅的模式,不需要每个消费者维护自己的消息队列,生产者将消息发送到topic,消费者订阅此topic 读取消息. 基本概念: 消息模型:消息模型包括producer,co ...

随机推荐

  1. Blocks(POJ 3734)

    原题如下: Blocks Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8020   Accepted: 3905 Desc ...

  2. [LeetCode] 46. 全排列(回溯)

    ###题目 给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], ...

  3. 部署cobbler服务器

    部署cobbler服务器 1.准备环境使用nat或者仅主机模式,不要使用桥接模式,方式获取的IP不是自己的 2. 配置yum源[epel]name=epelenabled=1gpgcheck=0bas ...

  4. Git+Gitlab+Ansible的roles实现一键部署Nginx静态网站(4)

    前言 截止目前已经写了<Ansible基础认识及安装使用详解(一)–技术流ken>,<Ansible常用模块介绍及使用(二)–技术流ken><Ansible剧本介绍及使用 ...

  5. iscroll5 滚动条根据内容高度自动显示隐藏及强制横屏时方向错位

    横竖屏方向错位: move: function (e) { if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { r ...

  6. Python爬虫练习:爬取800多所大学学校排名、星级等

    前言 国内大学最新排名,北大反超,浙大仅第四,中科大跌至第八 时隔五年,"双一流"大学即将迎来首次大考,这也是继改变高校评断标准之后,第一次即将以官方对外发布,自然是引来了许多人的 ...

  7. Java基础一篇过(八)常见异常速查

    一.引言 开发过程中可能会遇到各种各样的异常,这里还是汇总一些比较典型的异常,有些比较直观的异常如空指针这种就不写了,此文可作为异常速查用. 二.异常大军正在来袭~ IllegalArgumentEx ...

  8. Oracle学习(十一)聚合函数

    AVG() 求平均数 --查询某列的平均值 SELECT AVG(列) FROM 表 COUNT()查询条数 -- 查询所有记录的条数 select count(*) from 表; -- 查询对应列 ...

  9. P4395 [BOI2003]Gem 气垫车

    树形dp 首先,我们可以考虑dp,把这个问题看成一个树的染色问题,用dp[i][j]表示以i为根节点,将树染成第i种颜色的最小代价,那么我们可以得到j的最大值是(log(maxn)/log(2)+1) ...

  10. Anaconda, conda, pyenv, virtualenv的区别

    1.Python环境 Python解释器--Python.exe Python包集合--Lib,包括自带包和第三方包 2.Anaconda--一个科学计算环境,Python的发行版本 包括了Conda ...