springboot 中事件监听模型的一种实现
前言: 事件监听模型是一种常用的设计模式,在springboot 中我们如何实现呢?
首先我们要理解事件监听中需要的几个角色
- 事件发布者 (即事件源)
- 事件监听者
- 事件本身
废话不多说直接上代码
定义事件本身
事件本身需要继承ApplicationEvent
package com.yxd;
import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationEvent;
public class DemoEvent extends ApplicationEvent{
private String type;
private List<Map> msg;
public DemoEvent(Object object, String type ,List<Map> msg) {
super(object);
this.msg = msg;
this.type = type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<Map> getMsg() {
return msg;
}
public void setMsg(List<Map> msg) {
this.msg = msg;
}
}
如图:
定义事件源
事件源需要注入 **ApplicationContext **
package com.yxd;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class DemoPublisher {
@Autowired
ApplicationContext applicationContext;
public void publish(DemoEvent event) {
applicationContext.publishEvent(event);
}
}
定义监听者
监听者有两种实现
一、需要实现 ApplicationListener
package com.yxd;
import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class DemoListener1 implements ApplicationListener<DemoEvent> {
@Override
public void onApplicationEvent(DemoEvent event) {
List<Map> msg = event.getMsg();
String type = event.getType();
System.out.println(" listener1接收到了 publisher 发送的消息 , 时间 "+ Time.getTime());
System.out.println("listener1 : 类型 :" + type +", 消息内容: " + msg + ", 消息处理完毕! "+ Time.getTime());
}
}
二、使用 @EventListener 注解
package com.yxd;
import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class DemoListener2 {
@EventListener
public void onDemoEvent(DemoEvent demoEvent) {
System.out.println(" listener2 通过注解接收到了 publisher 发送的消息 , 时间 "+ Time.getTime());
List<Map> msg = demoEvent.getMsg();
String type = demoEvent.getType();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("listener2 : 类型 :" + type +", 消息内容: " + msg + ", 消息处理完毕! "+ Time.getTime());
}
}
此处我们还需要注意一点,此处多个监听是同步执行的(阻塞),一般情况下我们发布一个事件,是不关心谁来处理,以及处理结果的,所以我们还需要加上异步的注解
package com.yxd;
import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class DemoListener3 implements ApplicationListener<DemoEvent> {
@Override
@Async
public void onApplicationEvent(DemoEvent event) {
System.out.println(" listener3 接收到了 publisher 发送的消息 , 时间 "+ Time.getTime());
List<Map> msg = event.getMsg();
String type = event.getType();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("listener3 异步执行:类型 :" + type +", 消息内容: " + msg+ ", 消息处理完毕! "+ Time.getTime());
}
}
测试
package com.yxd;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@EnableAsync
@SpringBootApplication
@RestController
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Autowired
DemoPublisher demoPublisher;
@RequestMapping("testListener")
public String testListener() {
ArrayList<Map> list = new ArrayList<>();
HashMap<String, String> m1 = new HashMap<>();
m1.put("1", "2");
HashMap<String, String> m2 = new HashMap<>();
m2.put("3", "4");
HashMap<String, String> m3 = new HashMap<>();
m3.put("5", "6");
list.add(m1);
list.add(m2);
list.add(m3);
System.out.println("开始发布消息: " + Time.getTime());
demoPublisher.publish(new DemoEvent(this,"测试消息",list));
System.out.println("消息发布结束: " + Time.getTime());
return "消息发布成功";
}
}
我们访问接口
三个监听者都得到了消息。。
但是 listener2 通过注解 先得到了消息,延时2秒后,listener1 才得到消息,listener1 处理完后,主线程继续执行,同时listener3 开始接收到消息,开启了一个异步任务,3秒后执行结束
项目结构
最后附上Time类
package com.yxd;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Time {
public static String getTime() {
return new SimpleDateFormat("HH:mm:ss").format(new Date());
}
}
springboot 中事件监听模型的一种实现的更多相关文章
- SpringBoot Application事件监听
SpringBoot Application共支持6种事件监听,按顺序分别是: ApplicationStartingEvent:在Spring最开始启动的时候触发 ApplicationEnviro ...
- SpringBoot的事件监听
事件监听的流程分为三步:1.自定义事件,一般是继承ApplicationEvent抽象类.2.定义事件监听器,一般是实现ApplicationListener接口.3.a.启动的时候,需要将监听器加入 ...
- SpringBoot中如何监听两个不同源的RabbitMQ消息队列
spring-boot如何配置监听两个不同的RabbitMQ 由于前段时间在公司开发过程中碰到了一个问题,需要同时监听两个不同的rabbitMq,但是之前没有同时监听两个RabbitMq的情况,因此在 ...
- ASP.NET Core中配置监听URLs的五种方式
原文: 5 ways to set the URLs for an ASP.NET Core app 作者: Andrew Lock 译者: Lamond Lu 默认情况下,ASP. NET Core ...
- springboot~ EventListener事件监听的使用
EventListener事件触发和监听器可以对代码解耦,在一些与业务无关的,通用的操作方法,我们可以把它设计成事件监听器,像通知,消息这些模块都可以这样设计. 事件源 @Getter @Builde ...
- SpringBoot事件监听机制及观察者模式/发布订阅模式
目录 本篇要点 什么是观察者模式? 发布订阅模式是什么? Spring事件监听机制概述 SpringBoot事件监听 定义注册事件 注解方式 @EventListener定义监听器 实现Applica ...
- Spring之事件监听(观察者模型)
目录 Spring事件监听 一.事件监听案例 1.事件类 2.事件监听类 3.事件发布者 4.配置文件中注册 5.测试 二.Spring中事件监听分析 1. Spring中事件监听的结构 2. 核心角 ...
- SpringBoot事件监听机制源码分析(上) SpringBoot源码(九)
SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringApplicat ...
- jQuery中的事件监听小记
一,一个事件监听的简便写法 最近发现一个jQuery中事件监听的简洁写法,感觉方便好多.同时也深感自己基础薄弱,好多东西竟然都模棱两可.因此,记录的同时,也对jQuery事件监听做个小的总结 原文链接 ...
随机推荐
- (网页)Angular.js 中 copy 赋值与 = 赋值 区别
转自st.gg Angular.js 中 copy 赋值与 = 赋值 区别 为什么用 $scope.user = $scope.master; $scope.master 会跟着 $scope.use ...
- Azure 标准与高级托管磁盘存储的相互转换
托管磁盘提供两种存储选项:高级(基于 SSD)和标准(基于 HDD). 它允许基于性能需求在这两个选项之间轻松切换,并保障最短停机时间. 非托管磁盘不具备此功能. 但可以轻松转换为托管磁盘,以便在这两 ...
- JS代码段:VUE下的时间,星期和年月日
不为别的,只为以后复制粘贴方便 data() { return { date: "", time: "", week: "" }; }, / ...
- 常用DOS命令之通俗易懂篇
目录 常用DOS命令之通俗易懂篇 Arp 命令 Assoc 关联 At 计划服务 Attrib 属性 Cd=chdir 目录 Cipher Cls 清屏 Color 颜色 Comp 比较 Compac ...
- Linux 小知识翻译 - 「TCP/IP」
上次说了「协议」相关的话题,这次专门说说「TCP/IP」协议. 这里的主题是「TCP/IP」到底是什么?但并不是要说明「TCP/IP」是什么东西,重点是「TCP/IP」究竟有什么意义,在哪里使用「TC ...
- python基础 - 变量与运算符
变量与运算符 变量 定义一个变量 a = [1,2,3,4,5,6] print(a) # [1,2,3,4,5,6] 变量命名要求: 首字母不能是数字 只能包含字符数字下划线 不能是关键字 type ...
- Java设计模式之二 ----- 工厂模式
在上一篇中我们学习了单例模式,介绍了单例模式创建的几种方法以及最优的方法.本篇则介绍设计模式中的工厂模式,主要分为简单工厂模式.工厂方法和抽象工厂模式. 简单工厂模式 简单工厂模式是属于创建型模式,又 ...
- 小程序布局中class='container'的bug
display:flex失效,并增加其他额外属性,暂时记录,还未查询是何原因导致,更改calss则无此问题.
- 使用POI转换word doc文件
目录 1 转换为Html文件 2 转换为Xml文件 3 转换为Text文件 在POI中还存在有针对于word doc文件进行格式转换的功能.我们可以将word的内容 ...
- __iter___和__next__方法
__iter__方法变成一个迭代器类对象, 迭代器类要实现__next__方法