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

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

常见的例子:

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

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

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

说明:刘宏缔的架构森林是一个专注架构的博客,地址: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. 关于如何设置IDEA中的servlet的模板

    关于如何设置IDEA中的servlet的模板 点击左上角的File: Setting --> Editor --> File and Code Templates --> Other ...

  2. json模块:json.dumps()、json.loads()、json.dump()、json.load()

    json.dumps().json.loads().json.dump().json.load() 4个方法的总结和使用: 注意:存在文件里面的东西,读出来都是字符串 import json 1.js ...

  3. 吴恩达《深度学习》-课后测验-第三门课 结构化机器学习项目(Structuring Machine Learning Projects)-Week1 Bird recognition in the city of Peacetopia (case study)( 和平之城中的鸟类识别(案例研究))

    Week1 Bird recognition in the city of Peacetopia (case study)( 和平之城中的鸟类识别(案例研究)) 1.Problem Statement ...

  4. WeihanLi.Npoi 1.10.0 更新日志

    WeihanLi.Npoi 1.10.0 更新日志 Intro 上周有个网友希望能够导入Excel时提供一个 EndRowIndex 来自己控制结束行和根据字段过滤的,周末找时间做了一下这个 feat ...

  5. MySQL页分裂和页合并

    预备知识了解,索引页,数据页,b+tree 页是innoDB中管理储存空间的基本单位,页有很多中,存放数据的叫做索引页.

  6. springboot中图标的定制

    因为我用的版本是org.springframework.boot spring-boot-starter-parent 2.3.3.RELEASE 第一种方法: 配置一个application.yml ...

  7. yum管理——yum常用配置(2)

    一.网络源的缓存设置 [root@yunwei ~]# vim /etc/yum.conf [main] cachedir=/var/cache/yum/$basearch/$releasever k ...

  8. Netty之ChannelOption的各种参数之EpollChannelOption.SO_REUSEPORT

    socket选项 SO_REUSEPORT 转 miffa 发布于 2015/03/24 17:21 字数 3383 阅读 6076 收藏 6 点赞 1 评论 0 开发十年,就只剩下这套Java开发体 ...

  9. hystrix源码小贴士之之hystrix-metrics-event-stream

    hystrix-metrics-event-stream主要提供了一些servlet,可以让用户通过http请求获取metrics信息. HystrixSampleSseServlet 继承了Http ...

  10. 本机浏览器无法访问linux的tomcat

    原因:Centos7的防火墙拦截了tomcat访问的8080端口  Redhat 等等linux firewall-cmd --permanent --zone=public --add-port=8 ...