使用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/123378.html

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

相关文章

msvcr120.dll放在哪里?怎么修复msvcr120.dll文件

当您在运行某些应用程序或游戏时遇到“msvcr120.dll缺失”错误时&#xff0c;这可能会影响您的使用体验。msvcr120.dll是Microsoft Visual C Redistributable的一部分&#xff0c;并且它提供了程序运行所需的运行时支持&#xff0c;今天我们来讨论一下msvcr120.dl文件缺失了要怎…

祝贺埃文科技入选河南省工业企业数据安全技术支撑单位

近日&#xff0c;河南省工业信息安全产业发展联盟公布了河南省工业信息安全应急服务支撑单位和河南省工业企业数据安全技术支撑单位遴选结果,最终评选出19家单位作为第一届河南省工业信息安全应急服务支撑单位和河南省工业企业数据安全技术支撑单位。 埃文科技凭借自身技术优势…

leetcode 20.有效括号 栈的简单应用

题目 数据结构 栈 code var isValid function(s) {// 空串和长度为奇数的字符串一定不符合要求if(!s || s.len%2){return true}let match {(: ),[: ],{: }}let stack []let len s.lengthfor(let i0; i<len; i){const ch s[i]if(ch[ || ch( || ch{){// 如果是左括号,…

2.k8s账号密码登录设置

文章目录 前言一、启动脚本二、配置账号密码登录2.1.在hadoop1&#xff0c;也就是集群主节点2.2.在master的apiserver启动文件添加一行配置2.3 绑定admin2.4 修改recommended.yaml2.5 重启dashboard2.6 登录dashboard 总结 前言 前面已经搭建好了k8s集群&#xff0c;现在设置下…

python Playwright优化页面等待和处理异步操作

在使用 Playwright 进行页面自动化时&#xff0c;优化页面等待和处理异步操作是非常重要的&#xff0c;可以提高脚本的稳定性和执行效率。 优化页面等待和处理异步操作的建议 **1. 使用正确的等待条件&#xff1a;**Playwright 提供了多种等待条件&#xff0c;如等待元素出现…

2023年9月软考高级信息系统项目管理师认证报名找弘博创新

信息系统项目管理师是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目之一&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职称资…

Excel VSTO开发8 -相关控件

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 8 相关控件 在VSTO开发中&#xff0c;Ribbon&#xff08;或称为Ribbon UI&#xff09;是指Office应用程序中的那个位于顶部的带有选…

Python实现猎人猎物优化算法(HPO)优化BP神经网络分类模型(BP神经网络分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 猎人猎物优化搜索算法(Hunter–prey optimizer, HPO)是由Naruei& Keynia于2022年提出的一种最新的…

【C++】—— 单例模式详解

前言&#xff1a; 本期&#xff0c;我将要讲解的是有关C中常见的设计模式之单例模式的相关知识&#xff01;&#xff01; 目录 &#xff08;一&#xff09;设计模式的六⼤原则 &#xff08;二&#xff09;设计模式的分类 &#xff08;三&#xff09;单例模式 1、定义 2、…

【数学建模竞赛】优化类赛题常用算法解析

优化类建模 问题理解和建模&#xff1a;首先&#xff0c;需要深入理解问题&#xff0c;并将问题抽象为数学模型。这包括确定问题的目标函数、约束条件和决策变量。 模型分析和求解方法选择&#xff1a;对建立的数学模型进行分析&#xff0c;可以使用数学工具和方法&#xff0c;…

【vue】使用无障碍工具条(详细)

引入&#xff1a;使用的是太阳湾的无障碍工具条&#xff0c;代码地址&#xff1a;https://gitee.com/tywAmblyopia/ToolsUI 具体步骤&#xff1a;下载代码后&#xff0c;将其中的 canyou 文件夹拖入 vue 项目中的 public 文件夹中&#xff1b; 上图是在项目目录中的样子&#…

【计算机视觉项目实战】中文场景识别

✨专栏介绍: 经过几个月的精心筹备,本作者推出全新系列《深入浅出OCR》专栏,对标最全OCR教程,具体章节如导图所示,将分别从OCR技术发展、方向、概念、算法、论文、数据集等各种角度展开详细介绍。 👨‍💻面向对象: 本篇前言知识主要介绍深度学习知识,全面总结知知识…

Android Ble蓝牙App(七)扫描过滤

Ble蓝牙App&#xff08;七&#xff09;扫描过滤 前言目录正文一、增加菜单二、使用MMKV① 添加依赖② 封装MMKV③ 使用MMKV 三、过滤空设备名四、过滤Mac地址五、过滤RSSI六、源码 前言 在上一篇文章中了解了MTU的相关知识以及对于设备操作信息的展示&#xff0c;本篇文章中将增…

基于SSM的校园驿站管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

Android Studio开发入门教程:如何更改APP的图标?

更改APP的图标&#xff08;安卓系统&#xff09; 环境&#xff1a;Windows10、Android Studio版本如下图、雷电模拟器。 推荐图标库 默认APP图标 将新图标拉进src/main/res/mipmap-hdpi文件夹&#xff08;一般app的icon图标是存放在mipmap打头的文件夹下的&#xff09; 更改sr…

NoSQL技术——Redis

简单介绍 Redis是当下最流行的NoSQL数据库。在Redis中&#xff0c;数据的存储格式是以键值对的方式进行存储的。在键值对的存储形式中&#xff0c;值除了是常见的字符串&#xff0c;也可以是类似于Json对象的形式&#xff0c;或者是List&#xff0c;Map等数组格式&#xff0c;…

leetcode 92.反转链表II dummy节点的应用

题目 方法 dummy节点 链表的第一个结点&#xff0c;因为没有前驱结点&#xff0c;存在同时删除前驱和后继的情况&#xff0c;这时候我们需要人为构造dummy节点——人为制造出来的第一个结点的前驱结点&#xff0c;也就是说&#xff0c;在可能操作head节点时&#xff0c;我们可…

【CAD二次开发】重新加载acad.pgp快捷菜单文件

为了加快绘图速度&#xff0c;好多人会进行CAD快捷命令的修改&#xff0c;那怎么在不需要重启CAD的情况下自动更新&#xff1f; CAD修改acad.pgp,快捷命令后&#xff0c;自动更新。 方法一 命令行输入reinit&#xff0c;命令。 在弹出的窗口中&#xff0c;选择‘PGP文件’&…

腾讯汤道生:超千亿参数 超2万亿tokens 腾讯混元大模型向行业全面开放

9月7日&#xff0c;2023腾讯全球数字生态大会在深圳宝安举行。腾讯集团高级执行副总裁、云与智慧产业事业群CEO汤道生表示&#xff0c;腾讯将迈入“全面拥抱大模型”时代&#xff1a;“以大模型生成技术为核心&#xff0c;人工智能正在成为下一轮数字化发展的关键动力&#xff…

了解 glTF 2.0 格式

推荐&#xff1a;使用 NSDT场景编辑器快速搭建3D应用场景 介绍 glTF 代表 GL 传输格式。 glTF 是一种用于存储和加载 3D 场景的标准化文件格式&#xff0c;其基本目的是由 3D 创建工具轻松生成并被任何图形应用程序使用&#xff0c;无论使用何种 API&#xff0c;处理最少。 …