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. ...
随机推荐
- Java 读取Word文本/段落格式属性
本文介绍通过Java后端程序代码来读取Word文本和段落格式的方法. 本次测试环境如下: Word版本:2013 编译环境:IntelliJ IDEA2018 Work库:free spire.doc ...
- Java网络编程快速上手(SE基础)
参考资料:百度百科TCP协议 本文涉及Java IO流.异常的知识,可参考我的另外的博客 一文简述Java IO 一文简述JAVA内部类和异常 1.概述 计算机网络相关知识: OSI七层模型 一个报文 ...
- MySQL数据库高级一:架构介绍
两天半就可以 严禁使用 精通 在简历上 了解的越多,越比他人有优势 linux的mysql需要使用中文字符集那么就要修改配置文件 1.mysql的linux版 安装和卸载不说了 2.逻辑架构 总体概况 ...
- 【pytest官方文档】解读Skipping test functions,跳过测试用例详解
有时候,为了满足某些场景的需要,我们知道有些测试函数在这时候肯定不能执行,或者执行了也会失败.那么我们 可以选择去跳过这个测试函数,这样也就不会影响整体的测试函数运行效果,不至于在你运行的众多绿色通过 ...
- redhat 7.6 安装Python3后配置 yum pip3 升级openssl
安装python3后需要重新配置yum 配置yum vim /usr/bin/yum #! /usr/bin/python #修改前#! /usr/bin/python2 #修改后 vim /usr/ ...
- 19. slot插槽传递模板
插槽,也就是slot,是组件的一块HTML模板,这块模板显示不显示.以及怎样显示由父组件来决定. 插槽模板是slot,它是一个空壳子,因为它显示与隐藏以及最后用什么样的html模板显示由父组件控制.但 ...
- C#如何优雅的多表读取
关键词:C#.SqlDataReader.IDataReader.NextResult().Read(). Load().Dapper.多表,方便索引和搜索 最近有个需求,需要读一下模具系统的模具信息 ...
- linux删除文件空间不释放问题解决
目录 场景描述 原因 解决方法 在线清空文件 场景描述 某天,收到Prometheus报警,生产中某台机器出现磁盘空间不足报警,该台服务器是mysql其中一台从库,远程登录到该服务后,排查磁盘空间的原 ...
- css单位介绍em ex ch rem vw vh vm cm mm in pt pc px
长度单位主要有以下几种em ex ch rem vw vh vm cm mm in pt pc px %,大概可以分为几种"绝对单位"和"相对单位"和" ...
- thinkphp5 ztree树形菜单
教程:http://makaidong.com/zjfjava/4074_5873678.html 下载:https://github.com/zTree/zTree_v3