使用spring自带的发布订阅来实现发布订阅
背景
公司的项目以前代码里面有存在使用spring自带发布订阅的代码,因此稍微学习一下如何使用,并了解一下这种实现方式的优缺点。
优点
- 实现方便,代码方面基本只需要定义消息体和消费者,适用于小型应用程序。
- 不依赖外部中间件,因而不需要复杂的配置、部署。
缺点
- 无法提供消息持久性,项目一旦重启,消息就会丢失,因而不适合实现延迟队列。
- 对比消息队列,无法实现复杂的消息过滤、路由过滤。
- 无法实现跨应用程序的事件通信。不同应用程序之间的事件发布和订阅更为容易。
发布订阅模式的优缺点我就不说了,就说说不同实现方式之间的优缺点。
一、创建消息类
消息类需要继承ApplicationEvent类。因为java调用构造函数的机制就是默认会调用父类的构造函数,而ApplicationEvent类只有一个单参数的构造函数,无法自动调用,每个构造函数都需要显式调用父类的构造函数。也就是super(source);
package org.jeecg.modules.test.testPublic;
import org.springframework.context.ApplicationEvent;
import java.util.Objects;/*** @ClassName: MyEvent* @Author: zjc* @Date: 2023/8/30 18:22* @Description:**/
public class MyEvent extends ApplicationEvent {private String taskId;private Integer sourceType;public MyEvent(Object source) {super(source);}/**** @param source 触发事件的对象,可随便传,不过建议传自己可能用得到的对象。好像在调用放直接this的挺多* @param taskId 任务id,自己定义的事件要处理的内容* @param sourceType 自己定义的源类型,用来在多场景触发情况下区分不同场景的标志* @return: null**/public MyEvent(Object source,String taskId,Integer sourceType) {super(source);this.taskId=taskId;this.sourceType=sourceType;}public String getTaskId() {return taskId;}public void setTaskId(String taskId) {this.taskId = taskId;}public Integer getSourceType() {return sourceType;}public void setSourceType(Integer sourceType) {this.sourceType = sourceType;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;MyEvent myEvent = (MyEvent) o;return Objects.equals(taskId, myEvent.taskId) && Objects.equals(sourceType, myEvent.sourceType);}@Overridepublic int hashCode() {return Objects.hash(taskId, sourceType);}@Overridepublic String toString() {return "MyEvent{" +"taskId='" + taskId + '\'' +", sourceType=" + sourceType +'}';}
}
二、发布消息
发布消息可以直接使用ApplicationContext对象调用publishEvent方法。因为ApplicationContext接口继承了ApplicationEventPublisher接口。注意消息类必须要继承ApplicationEvent类才能作为参数发布消息。
package org.jeecg.modules.test.testPublic;import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @ClassName: EventController* @Author: * @Date: 2023/8/31 17:53* @Description:**/
@RestController
@Api("test")
@RequestMapping("/test")
public class EventController {@Autowiredprivate ApplicationContext applicationContext;@ApiOperation("testEvent")@GetMapping("/testEvent")public void testEvent(){MyEvent myEvent=new MyEvent(this,"123456",1);applicationContext.publishEvent(myEvent);}@ApiOperation("testEvent1")@GetMapping("/testEvent1")public void testEvent1(){MyEvent myEvent=new MyEvent(this,"123456",2);applicationContext.publishEvent(myEvent);}
}
三、监听消息
监听消息类需要实现ApplicationListener接口,并通过泛型传入要监听的消息类,并重写onApplicationEvent方法。spring内的同一个消息可以有多个监听类,一旦监听到消息,监听该消息的全部监听类都会执行。
监听类1:
package org.jeecg.modules.test.testPublic;import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;/*** @ClassName: MyEventListener* @Author: * @Date: 2023/8/31 17:50* @Description:**/
@Component
public class MyEventListener implements ApplicationListener<MyEvent> {@Overridepublic void onApplicationEvent(MyEvent event) {System.out.println("消费者开始消费"+event.toString()+event.getSource().toString());}
}
消费者2
package org.jeecg.modules.test.testPublic;import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;/*** @ClassName: MyEventListener* @Author: * @Date: 2023/8/31 17:50* @Description:**/
@Component
public class MyEventListener1 implements ApplicationListener<MyEvent> {@Overridepublic void onApplicationEvent(MyEvent event) {System.out.println("消费者1开始消费"+event.toString()+event.getSource().toString());}
}
四、测试
调用testEvent接口
调用testEvent1接口
结果均符合预期,可以通过在消息体里面加一个字段来区分消息来着不同的触发场景。
即使没有在结构体加上区分消息来源的标识,也可以用消息一开始传入的源对象来大概定位到是哪一个类里面触发的消息。
相关文章:

使用spring自带的发布订阅来实现发布订阅
背景 公司的项目以前代码里面有存在使用spring自带发布订阅的代码,因此稍微学习一下如何使用,并了解一下这种实现方式的优缺点。 优点 实现方便,代码方面基本只需要定义消息体和消费者,适用于小型应用程序。不依赖外部中间件&a…...

Walmart电商促销活动即将开始,如何做促销活动?需要注意什么?
近日,沃尔玛官宣Baby Days优惠活动将于9月1日正式开始!卖家可以把握机会,通过设置促销定价,以最优惠的婴儿相关产品价格吸引消费者,包括汽车座椅、婴儿车、尿布袋、家具、床上用品、消耗品、婴儿服装、孕妇装等。注意本…...

Matlab(画图进阶)
目录 大纲 1.特殊的Plots 1.1 loglog(双对数刻度图) 1.3 plotyy(创建具有两个y轴的图形) 1.4yyaxis(创建具有两个y轴的图) 1.5 bar 3D条形图(bar3) 1.6 pie(饼图) 3D饼图 1.7 polar 2.Stairs And Ste阶梯图 3.Boxplot 箱型图和Error Bar误差条形图 3.1 boxplot 3.2 …...

人生的回忆
回忆是人类宝贵的精神财富,它们像一串串珍珠,串联起我们生活中的每一个片段。 回忆是时间的见证者,它们承载着我们成长、经历、悲欢离合的点点滴滴。 回忆让我们重温过去的欢笑与眼泪,感受那些已经逝去的时光。它们就像一本翻开的…...

Spring之依赖注入源码解析
Spring之依赖注入源码解析 Spring依赖注入的方式 手动注入 在XML中定义Bean时,即为手动注入,因为是程序员手动给某个属性指定了值。 通过set方式进行注入 <bean name"userService" class"com.luban.service.UserService">…...

5G NR:RACH流程-- Msg1之生成PRACH Preamble
随机接入流程中的Msg1,即在PRACH信道上发送random access preamble。涉及到两个问题: 一个是如何产生preamble?一个是如何选择正确的PRACH时频资源发送所选的preamble? 一、PRACH Preamble是什么 PRACH Preamble从数学上来讲是一个长度为…...

高基数类别特征预处理:平均数编码 | 京东云技术团队
一 前言 对于一个类别特征,如果这个特征的取值非常多,则称它为高基数(high-cardinality)类别特征。在深度学习场景中,对于类别特征我们一般采用Embedding的方式,通过预训练或直接训练的方式将类别特征值编…...

高效利用隧道代理实现无阻塞数据采集
在当今信息时代,大量的有价值数据分散于各个网站和平台。然而,许多网站对爬虫程序进行限制或封禁,使得传统方式下的数据采集变得困难重重。本文将向您介绍如何通过使用隧道代理来解决这一问题,并帮助您成为一名高效、顺畅的数据采…...

图论岛屿问题DFS+BFS
leetcode 200 岛屿问题 class Solution {//定义对应的方向boolean [][] visited;int dir[][]{{0,1},{1,0},{-1,0},{0,-1}};public int numIslands(char[][] grid) {//对应的二维数组int count0;visitednew boolean[grid.length][grid[0].length];for (int i 0; i < grid.l…...

Cypress web自动化windows环境npm安装Cypress
前言 web技术已经进化了,web的测试技术最终还是跟上了脚步,新一代的web自动化技术出现了? Cypress可以对在浏览器中运行的任何东西进行快速、简单和可靠的测试。 官方地址https://www.cypress.io/,详细的文档介绍https://docs.cypress.io/g…...

CentOS7.9设置ntp时间同步
文章目录 应用场景基础知识操作步骤 应用场景 我们公司是做智慧交通的,主要卖交通相关的硬件和软件。硬件包括信号机、雷达、雷视、边缘盒子等,软件包括信控平台、管控平台等信号机设备、雷达设备、边缘计算单元等,还有一些第三方的卡口设备…...

36、springboot --- 对 tomcat服务器 和 undertow服务器 配置访客日志
springboot 配置访客日志 ★ 配置访客日志: 访客日志: Web服务器可以将所有访问用户的记录都以日志的形式记录下来,主要就是记录来自哪个IP的用户、在哪个时间点、访问了哪个资源。 Web服务器可将所有访问记录以日志形式记录下来ÿ…...

MySQL表的增删改查
文章目录 MySQL表的增删改查1. Create1.1 单行数据插入1.2 多行数据插入1.3 插入否则更新1.4 替换 2. Retrieve2.1 SELECT 列2.1.1 全列查询2.1.2 指定列查询2.1.3 查询字段为表达式2.1.4 为查询结果指定别名2.1.5 结果去重 2.2 WHERE 条件2.2.1 英语不及格的同学及英语成绩(&l…...

yolov3
yolov1 传统的算法 最主要的是先猜很多候选框,然后使用特征工程来提取特征(特征向量),最后使用传统的机器学习工具进行训练。然而复杂的过程可能会导致引入大量的噪声,丢失很多信息。 从传统的可以总结出目标检测可以分为两个阶…...

基于低代码/无代码工具构建 BI 应用程序
一、前言 随着数字化推进,越来越多的企业开始重视数据分析,希望通过BI(商业智能)技术提高业务决策的效率和准确性。 传统的BI解决方案往往需要大量的定制开发和数据准备,不仅周期长、成本高,还需要专业的数…...

Servlet与过滤器
目录 Servlet 过滤器 Servlet Servlet做了什么 本身不做任何业务处理,只是接收请求并决定调用哪个JavaBean去处理请求,确定用哪个页面来显示处理返回的数据 Servlet是什么 ServerApplet,是一种服务器端的Java应用程序 只有当一个服务器端的程序使用了Servlet…...

微信小程序开发实战记录
近期公司需要开发一个小程序项目,时间非常紧急,在开发过程中遇到几个困扰的问题及解决方案,记录如下:小程序框架选择 基础框架:小程序原生框架 sassui: 采用 vant weapp图表:采用 ec-echarts …...

防破解暗桩思路:检查菜单是否被非法修改过源码
本篇文章属于《518抽奖软件开发日志》系列文章的一部分。 我在开发《518抽奖软件》(www.518cj.net)的时候,为了防止被破解,需用添加一些暗桩,在合适的时机检查软件是否被非法修改过,如果被非法修改就做出提…...

IDEA使用Docker插件
修改Docker配置 1.执行命令vim /usr/lib/systemd/system/docker.service,在ExecStart配置的后面追加 -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock ExecStart/usr/bin/dockerd -H fd:// --containerd/run/containerd/containerd.sock -H tcp://0.0.0.0:…...

[前端] vue使用Mousetrap.js实现快捷键
Mousetrap.js介绍 Mousetrap.js 是一个处理键盘快捷键的 JavaScript 库,它允许您定义复杂的键盘快捷键并在浏览器中使用。 官方地址 代码仓库 安装库 在命令行中运行以下命令安装 mousetrap 模块: npm install mousetrap再次运行命令行,安…...

如何查询Oracle的字符集
如何查询Oracle的字符集 很多人都碰到过因为字符集不同而使数据导入失败的情况。这涉及三方面的字符集,一是oracel server端的字符集,二是oracle client端的字符集;三是dmp文件的字符集。在做数据导入的时候,需要这三个字符集都一致才能正确…...

C语言每日一练------------Day(7)
本专栏为c语言练习专栏,适合刚刚学完c语言的初学者。本专栏每天会不定时更新,通过每天练习,进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字:两个数组的交集 双指针 💓博主csdn个人主页…...

Meta语言模型LLaMA解读:模型的下载部署与运行代码
文章目录 llama2体验地址模型下载下载步骤准备工作什么是Git LFS下载huggingface模型 模型运行代码 llama2 Meta最新语言模型LLaMA解读,LLaMA是Facebook AI Research团队于2023年发布的一种语言模型,这是一个基础语言模型的集合。 体验地址 体验地址 …...

人生中的孤独
孤独是一种深刻而痛苦的情感状态,在这个喧嚣而充满人群的世界中,许多人都曾经或正在经历孤独的阶段。 孤独并不仅仅是身边缺乏他人的陪伴,更是一种内心的空虚和失落。 孤独的人生可能来源于各种原因。 有些人可能因为缺乏亲密的人际关系&…...

掌握Spring框架核心组件:深入探讨IOC、AOP、MVC及注解方式面试指南【经验分享】
目录 引言 一、Spring IOC篇 1.什么是Spring 2.核心概念 3.核心架构 4.什么是控制反转(IOC) 5.依赖注入(DI) 二、Spring AOP篇 1.什么是AOP 2.Spring AOP代理机制 3.核心概念 4.通知分类 三、Spring MVC篇 1.什么…...

代码随想录算法训练营第37天 | ● 738.单调递增的数字 ● 968.监控二叉树 ● 总结
文章目录 前言一、738.单调递增的数字二、968.监控二叉树总结 前言 可以吗? 一、738.单调递增的数字 本题只要想清楚个例,例如98,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum…...

SOPC之NIOS Ⅱ实现电机转速PID控制(调用中断函数)
通过FPGA开发板上的NIOS Ⅱ搭建电机控制的硬件平台,包括电机正反转、编码器的读取,再通过软件部分实现PID算法对电机速度进行控制,使其能够渐近设定的编码器目标值。 一、问题与改进 SOPC之NIOS Ⅱ实现电机转速PID控制_STATEABC的博客-CSDN…...

ElasticSearch安装为Win11服务
在windows的环境下操作是Elasticsearch,并且喜欢使用命令行 ,启动时通过cmd直接在elasticsearch的bin目录下执行elasticsearch ,这样直接启动的话集群名称会默elasticsearch,节点名称会随机生成。 停止就直接在cmd界面按CtrlC 其实我们也可以将elasticse…...

ransac拟合平面,代替open3d的segment_plane
0.open3d打包太大了,所以决定网上找找代码 使用open3d拟合平面并且求平面的法向量,open3d打包大概1个g的大小。 import open3d as o3dpcd o3d.geometry.PointCloud()pcd.points o3d.utility.Vector3dVector(points)## 使用RANSAC算法拟合平面plane_m…...

Docker技术--Docker镜像管理
1.Docker镜像特性 ①.镜像创建容器的特点 Docker在创建容器的时候需要指定镜像,每一个镜像都有唯一的标识:image_id,也可也使用镜像名称和版本号做唯一的标识,如果不指定版本号,那么默认使用的是最新的版本标签(laster)。 ②.镜像分层机制 Docker镜像是分层构建的,并通过…...