SpringBoot系列——事件发布与监听
前言
日常开发中,我们经常会碰到这样的业务场景:用户注册,注册成功后需要发送邮箱、短信提示用户,通常我们都是这样写:
/**
* 用户注册
*/
@GetMapping("/userRegister")
public String userRegister(UserVo userVo) {
//校验参数 //存库 //发送邮件 //发送短信 //API返回结果
return "操作成功!";
}
可以发现,用户注册与信息推送强耦合,用户注册其实到存库成功,就已经算是完成了,后面的信息推送都是额外的操作,甚至信息推送失败报错,还会影响API接口的结果,如果在同一事务,报错信息不捕获,还会导致事务回滚,存库失败。
官方文档相关介绍:https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#boot-features-application-events-and-listeners
本文记录springboot使用@EventListener监听事件、ApplicationEventPublisher.publishEvent发布事件实现业务解耦。
代码
项目结构

默认情况下,事件的发布和监听操作是同步执行的,我们先配置一下async,优雅多线程异步任务,详情请戳:SpringBoot系列——@Async优雅的异步调用
启动类添加@EnableAsync注解
/**
* 异步任务线程池的配置
*/
@Configuration
public class AsyncConfig { private static final int MAX_POOL_SIZE = 50; private static final int CORE_POOL_SIZE = 20; @Bean("asyncTaskExecutor")
public AsyncTaskExecutor asyncTaskExecutor() {
ThreadPoolTaskExecutor asyncTaskExecutor = new ThreadPoolTaskExecutor();
asyncTaskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
asyncTaskExecutor.setCorePoolSize(CORE_POOL_SIZE);
asyncTaskExecutor.setThreadNamePrefix("async-task-");
asyncTaskExecutor.initialize();
return asyncTaskExecutor;
}
}
多数情况下的业务操作都会涉及数据库事务,可以使用@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)注解开启事务监听,确保数据入库后再进行异步任务操作。
定义事件源
先定义两个事件源,继承ApplicationEvent
/**
* 用户Vo
*/
@Data
public class UserVo { private Integer id; private String username;
} /**
* 用户事件源
*/
@Getter
@Setter
public class UserEventSource extends ApplicationEvent {
private UserVo userVo; UserEventSource(UserVo userVo) {
super(userVo);
this.userVo = userVo;
}
}
/**
* 业务工单Vo
*/
@Data
public class WorkOrderVo { private Integer id; private String WorkOrderName;
} /**
* 业务工单事件源
*/
@Getter
@Setter
public class WorkOrderEventSource extends ApplicationEvent {
private cn.huanzi.qch.springbooteventsandlisteners.pojo.WorkOrderVo WorkOrderVo; WorkOrderEventSource(WorkOrderVo WorkOrderVo) {
super(WorkOrderVo);
this.WorkOrderVo = WorkOrderVo;
}
}
监听事件
监听用户注册事件、监听业务工单发起事件
/**
* 事件监听
*/
@Slf4j
@Component
public class EventListenerList { /**
* 用户注册事件监听
*/
@Async("asyncTaskExecutor")
@EventListener
@Order(1)//一个事件多个事监听,使用@order值越小,执行顺序优先
public void userRegisterListener(UserEventSource eventSourceEvent){
log.info("用户注册事件监听1:"+eventSourceEvent.getUserVo()); //开展其他业务,例如发送邮件、短信等
}
/**
* 用户注册事件监听
*/
@Async("asyncTaskExecutor")
@EventListener
@Order(2)//一个事件多个事监听,使用@order值越小,执行顺序优先
public void userRegisterListener2(UserEventSource eventSourceEvent){
log.info("用户注册事件监听2:"+eventSourceEvent.getUserVo()); //开展其他业务,例如发送邮件、短信等
} /**
* 业务工单发起事件监听
*/
@Async("asyncTaskExecutor")
@EventListener
public void workOrderStartListener(WorkOrderEventSource eventSourceEvent){
log.info("业务工单发起事件:"+eventSourceEvent.getWorkOrderVo()); //开展其他业务,例如发送邮件、短信等
}
}
发布事件
创建一个controller,新增两个测试接口
/**
* 事件发布
*/
@Slf4j
@RestController
@RequestMapping("/eventPublish/")
public class EventPublish { @Autowired
private ApplicationEventPublisher applicationEventPublisher; /**
* 用户注册
*/
@GetMapping("userRegister")
public String userRegister(UserVo userVo) {
log.info("用户注册!"); //发布 用户注册事件
applicationEventPublisher.publishEvent(new UserEventSource(userVo)); return "操作成功!";
} /**
* 业务工单发起
*/
@GetMapping("workOrderStart")
public String workOrderStart(WorkOrderVo workOrderVo) {
log.info("业务工单发起!"); //发布 业务工单发起事件
applicationEventPublisher.publishEvent(new WorkOrderEventSource(workOrderVo)); return "操作成功!";
}
}
效果
用户注册
http://localhost:10010/eventPublish/userRegister?id=1&username=张三
API返回

后台异步任务执行

工单发起
http://localhost:10010/eventPublish/workOrderStart?id=1&workOrderName=设备出入申请单
API返回

后台异步任务执行

后记
springboot使用事件发布与监听就暂时记录到这,后续再进行补充。
代码开源
代码已经开源、托管到我的GitHub、码云:
GitHub:https://github.com/huanzi-qch/springBoot
码云:https://gitee.com/huanzi-qch/springBoot
SpringBoot系列——事件发布与监听的更多相关文章
- spring中的事件发布与监听
点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. spring事件发布与监听的应用场景 当处理完一段代码逻辑,接下来需要同 ...
- Spring知识点回顾(07)事件发布和监听
Spring知识点回顾(07)事件发布和监听 1.DemoEvent extends ApplicationEvent { public DemoEvent(Object source, String ...
- spring 自定义事件发布及监听(简单实例)
前言: Spring的AppilcaitionContext能够发布事件和注册相对应的事件监听器,因此,它有一套完整的事件发布和监听机制. 流程分析: 在一个完整的事件体系中,除了事件和监听器以外,还 ...
- Spring事件发布与监听机制
我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复[资料],即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板. 目录 ...
- SpringBoot | 第三十二章:事件的发布和监听
前言 今天去官网查看spring boot资料时,在特性中看见了系统的事件及监听章节.想想,spring的事件应该是在3.x版本就发布的功能了,并越来越完善,其为bean和bean之间的消息通信提供了 ...
- 关于JAVA中事件分发和监听机制实现的代码实例-绝对原创实用
http://blog.csdn.net/5iasp/article/details/37054171 文章标题:关于JAVA中事件分发和监听机制实现的代码实例 文章地址: http://blog.c ...
- JavaEE开发之Spring中的事件发送与监听以及使用@Profile进行环境切换
本篇博客我们就来聊一下Spring框架中的观察者模式的应用,即事件的发送与监听机制.之前我们已经剖析过观察者模式的具体实现,以及使用Swift3.0自定义过通知机制.所以本篇博客对于事件发送与监听的底 ...
- Pox启动及事件产生、监听分析
./pox/pox.py , Pox 实例化core=pox.core.initialize(),即为实例化POXCore类(该类是所有组件的交接点,提供组件注册功能),监听cor ...
- apiCloud事件发送与监听
apiCloud事件发送与监听 1.sendEvent 将任意一个自定义事件广播出去,该事件可在任意页面通过 addEventListener 监听收到. sendEvent({params}) 2. ...
随机推荐
- Android学习之CoordinatorLayout+AppBarLayout
•AppBarLayout 简介 AppbarLayout 是一种支持响应滚动手势的 app bar 布局: 基本使用 新建一个项目,命名为 TestAppBarLayout: 修改 activity ...
- 系统编程-信号-总体概述和signal基本使用
信号章节 -- 信号章节总体概要 信号基本概念 信号是异步事件,发送信号的线程可以继续向下执行而不阻塞. 信号无优先级. 1到31号信号是非实时信号,发送的信号可能会丢失,不支持信号排队. 31号信号 ...
- @PostConstruct 使用记录
@PostConstruct 从Java EE5规范开始,Servlet增加了两个影响Servlet生命周期的注解(Annotation):@PostConstruct和@PreConstruct.这 ...
- php-mysql-防止sql注入
1.防止sql注入-预准备 mysqli: $qSelect = $DBH->prepare("SELECT * FROM users WHERE username = ?" ...
- 虚拟机装好centos7没网解决办法
输入ip查询命名 ip addr 也可以输入 ifconfig(centOs7没有ifconfig命令)查看ip,但此命令会出现3个条目,centos的ip地址是ens33条目中的inet值. 发现 ...
- linux下Mysql 8.0.19 编译安装
1 前言 linux下安装MySQL的方式有很多种,包括以仓库的方式安装(yum,apt,zypper),以包的方式安装(rpm,deb),以docker方式安装,从压缩包解压安装,从源码编译安装,这 ...
- IDEA关于-javaagent中文路径导致无法debug的初步解决方案
IDEA明明是装在D盘的纯英文路径,而且java的相关环境变量全部是在英文路径,结果还是因为中文路径的问题导致无法debug.仔细观察,发现这个中文路径是作为java的-javaagent的参数输入的 ...
- C/C++ 构建系统,我用 xmake
XMake 是什么 XMake 是一个基于 Lua 的 现代化 C/C++ 构建系统. 它的语法简洁易上手,对新手友好,即使完全不会 lua 也能够快速入门,并且完全无任何依赖,轻量,跨平台. 同时, ...
- 1.人工智能解读与Python简介
人工智能解读 Python解读 Python 简介 1.程序员: 程序设计人员. 2.程序: 一组计算机能识别和执行的指令,是实现某种需求的软件. 3.操作系统: 管理和控制计算机软件与硬件资源的程序 ...
- 详谈lastIndex对正则结果的影响
前言 今天遇到一个问题,用正则表达式去检查同一个字符串时,交替返回true和false.无奈之下,重新翻了翻权威指南,发现罪魁祸首原来是lastIndex.可在控制台尝试下 ? 1 2 3 4 5 6 ...