使用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接口

在这里插入图片描述

结果均符合预期,可以通过在消息体里面加一个字段来区分消息来着不同的触发场景。
即使没有在结构体加上区分消息来源的标识,也可以用消息一开始传入的源对象来大概定位到是哪一个类里面触发的消息。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(数字图像处理MATLAB+Python)第十一章图像描述与分析-第一节、二节:图像描述概述和特征点

文章目录 一&#xff1a;图像描述概述&#xff08;1&#xff09;图像描述&#xff08;2&#xff09;描述子 二&#xff1a;特征点&#xff08;1&#xff09;Moravec角点检测A&#xff1a;原理B&#xff1a;程序 &#xff08;2&#xff09;Harris角点检测A&#xff1a;原理B&…

尚硅谷宋红康MySQL笔记 14-18

是记录&#xff0c;不会太详细&#xff0c;受本人知识限制会有错误&#xff0c;会有个人的理解在里面 第14章 视图 了解一下&#xff0c;数据库的常见对象 对象描述表(TABLE)表是存储数据的逻辑单元&#xff0c;以行和列的形式存在&#xff0c;列就是字段&#xff0c;行就是记…

排序之插入排序

文章目录 前言一、直接插入排序1、基本思想2、直接插入排序的代码实现3、直接插入排序总结 二、希尔排序1、希尔排序基本思想2、希尔排序的代码实现3、希尔排序时间复杂度 前言 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大…

【Vue】vue2预览显示quill富文本内容,vue-quill-editor回显页面,v-html回显富文本内容

文章目录 前言一、下载二、使用步骤1.引入样式2.html代码 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; vue后台框架&#xff0c;若依系统里有一个富文本编辑器&#xff0c;效果如下 在package.json里面查看&#xff0c;发现插件名叫quill 插件的…

基于食肉植物算法优化的BP神经网络(预测应用) - 附代码

基于食肉植物算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于食肉植物算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.食肉植物优化BP神经网络2.1 BP神经网络参数设置2.2 食肉植物算法应用 4.测试结果&#xff1a;5…

【Leetcode】130.被围绕的区域

一、题目 1、题目描述 给你一个 m x n 的矩阵 board ,由若干字符 X 和 O ,找到所有被 X 围绕的区域,并将这些区域里所有的 O 用 X 填充。 示例1: 输入:board = [[“X”,“X”,“X”,“X”],[“X”,“O”,“O”,“X”],[“X”,“X”,“O”,“X”],[“X”,“O”,“X”,“…

海外ios应用商店优化排名因素之视频预览与截图

当我们找到感兴趣的应用程序并转到该应用程序的页面时&#xff0c;首先引起注意的是预览视频。视频旨在以更具吸引力的方式展示应用程序的用户体验和UI。视频长度最多为30秒&#xff0c;其中前5秒最为重要&#xff0c;一定要让它尽可能引人注目。 1、关于优化预览视频的提示。…

【C语言】循环语句详解

✨个人主页&#xff1a; Anmia.&#x1f389;所属专栏&#xff1a; C Language &#x1f383;操作环境&#xff1a; Visual Studio 2019 版本 目录 1.什么是循环结构&#xff1f; 2.while循环 while流程图 while语句中的break和continue break continue 3.for循环 for流…

进程Start

Linux中的命令解释器和Windows的程序管理器explorer.exe一样地位,都是在用户态下运行的进程 共享变量发生不同进程间的指令交错&#xff0c;就可能会数据出错 进程只作为除CPU之外系统资源的分配单位 CPU的分配单位是线程 每个进程都有自己的独立用户空间 内核空间是OS内核的…

PyCharm切换虚拟环境

PyCharm切换虚拟环境 为了满足不同任务需要不同版本的包&#xff0c;可以在Anaconda或者Miniconda创建多个虚拟环境文件夹&#xff0c;并在PyCharm下切换虚拟环境。 解决方案 1、打开Ananconda Prompt 2、创建自己的虚拟环境 格式&#xff1a;conda create -n 虚拟环境名字…

PSP - 蛋白质结构预测 OpenFold Multimer 模型训练参数与配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132575709 OpenFold Multimer 是用于预测蛋白质多聚体结构的计算方法。基于OpenFold 的单体预测框架&#xff0c;利用深度学习技术&#xff0c;结…

dayjs格式转换成日期

目录 方法一&#xff1a; ​编辑方法二&#xff1a; 这个项目在筛选订单时间的时候是由前端进行筛选的&#xff0c;用的是adt-design-pro进行二开的&#xff0c;其中在用日期组件的时候遇到了一个问题&#xff0c;组件返回的是&#xff1a; 但是我需要的是年-月-日&#xff…

java八股文面试[数据库]——MySql聚簇索引和非聚簇索引区别

聚集索引和非聚集索引 聚集索引和非聚集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否一致。 1、聚集索引 聚集索引表记录的排列顺序和索引的排列顺序一致&#xff08;以InnoDB聚集索引的主键索引来说&#xff0c;叶子节点中存储的就是行数据&#xff0c;行数据在…

LeetCode 面试题 02.04. 分割链表

文章目录 一、题目二、C# 题解 一、题目 给你一个链表的头节点 head 和一个特定值 x&#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你不需要 保留 每个分区中各节点的初始相对位置。 点击此处跳转题目。 示例 1&#…

c# 本地化中英文切换

区域 线程默认区域为当前计算机所选区域 设置当前区域&#xff1a; Thread.CurrentThread.CurrentCulture new CultureInfo(“zh-cn”); 获取当前区域&#xff1a; Console.WriteLine(Thread.CurrentThread.CurrentCulture.ToString()); 区域名称&#xff1a; “zh-cn” 中文…

Spooling的原理

脱机技术 程序猿先用纸带机把自己的程序数据输入到磁带中&#xff0c;这个输入的过程是由一台专门的外围控制机实现的。之后CPU直接从快速的磁带中读取想要的这些输入数据。输出也类似。 假脱机技术&#xff08;Spooling技术&#xff09; 即用软件的方式来模拟脱机技术。要…

python爬虫14:总结

python爬虫14&#xff1a;总结 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 申明 ​ 本系列所涉及的代码仅用于个人研究与讨论&#xff0c;并不会对网站产生不好…

如何实现AI的矢量数据库

推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建3D应用场景 然而&#xff0c;人工智能模型有点像美食厨师。他们可以创造奇迹&#xff0c;但他们需要优质的成分。人工智能模型在大多数输入上都做得很好&#xff0c;但如果它们以最优化的格式接收输入&#xff0c;它们就会真正…

DNS指向别名还是IP

现在有一台服务器dbprod126&#xff0c;ip是172.22.100.4 现在有一个需求&#xff0c;需要在dns中对dbprod126建一个别名wondadb3r的记录&#xff0c;也就是ping wondadb3r的时候显示的是dbprod126的ip&#xff0c;目前有两​种方法&#xff0c;主要使用方法1指向别名&#xf…

【Docker】网络

文章目录 Docker 网络基础Docker网络管理Docker网络架构CNMLibnetwork驱动 常见的网络类型 Docker 网络管理命令docker network createdocker network inspectdocker network connectdocker network disconnectdocker network prunedocker network rmdocker network ls docker …