前言

  日常开发中,我们经常会碰到这样的业务场景:用户注册,注册成功后需要发送邮箱、短信提示用户,通常我们都是这样写:

    /**
* 用户注册
*/
@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系列——事件发布与监听的更多相关文章

  1. spring中的事件发布与监听

    点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. spring事件发布与监听的应用场景 当处理完一段代码逻辑,接下来需要同 ...

  2. Spring知识点回顾(07)事件发布和监听

    Spring知识点回顾(07)事件发布和监听 1.DemoEvent extends ApplicationEvent { public DemoEvent(Object source, String ...

  3. spring 自定义事件发布及监听(简单实例)

    前言: Spring的AppilcaitionContext能够发布事件和注册相对应的事件监听器,因此,它有一套完整的事件发布和监听机制. 流程分析: 在一个完整的事件体系中,除了事件和监听器以外,还 ...

  4. Spring事件发布与监听机制

    我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复[资料],即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板. 目录 ...

  5. SpringBoot | 第三十二章:事件的发布和监听

    前言 今天去官网查看spring boot资料时,在特性中看见了系统的事件及监听章节.想想,spring的事件应该是在3.x版本就发布的功能了,并越来越完善,其为bean和bean之间的消息通信提供了 ...

  6. 关于JAVA中事件分发和监听机制实现的代码实例-绝对原创实用

    http://blog.csdn.net/5iasp/article/details/37054171 文章标题:关于JAVA中事件分发和监听机制实现的代码实例 文章地址: http://blog.c ...

  7. JavaEE开发之Spring中的事件发送与监听以及使用@Profile进行环境切换

    本篇博客我们就来聊一下Spring框架中的观察者模式的应用,即事件的发送与监听机制.之前我们已经剖析过观察者模式的具体实现,以及使用Swift3.0自定义过通知机制.所以本篇博客对于事件发送与监听的底 ...

  8. Pox启动及事件产生、监听分析

        ./pox/pox.py , Pox       实例化core=pox.core.initialize(),即为实例化POXCore类(该类是所有组件的交接点,提供组件注册功能),监听cor ...

  9. apiCloud事件发送与监听

    apiCloud事件发送与监听 1.sendEvent 将任意一个自定义事件广播出去,该事件可在任意页面通过 addEventListener 监听收到. sendEvent({params}) 2. ...

随机推荐

  1. P1060_开心的金明(JAVA语言)

    思路 0/1背包问题 模板 //暴力出奇迹 题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些 ...

  2. go-ini入门教程

    go-ini入门教程 go-ini简介 Package ini provides INI file read and write functionality in Go. 在实际开发时,配置信息一般不 ...

  3. django常用模板语言

    一.变量 django模板接收到从后端传来的参数,放入模板中对应的变量中#django代码 def info(request): .... return render(request,'info.ht ...

  4. linux程序开机自动启动

    linux如果需要实现开机启动, 可以找到 $HOME/.config/autostart 目录(没有的话新建一个),在该文件夹下创建一个空文件,文件名自拟,后缀必须是desktop,如:dingda ...

  5. java例题_07 字符串的处理

    1 /*7 [程序 7 处理字符串] 2 题目:输入一行字符,分别统计出其中英文字母.空格.数字和其它字符的个数. 3 程分析:利用 while 语句,条件为输入的字符不为'\n'. 4 */ 5 6 ...

  6. Spring笔记(五)

    Spring 事务操作 一.事务(概念) 1. 什么是事务 事务是数据库的最基本单元,逻辑上的一组操作,要么都成功,如果有一个失败,那么所有的操作都失败 典型场景: lucy转账100元给mary l ...

  7. webpack核心模块tapable源码解析

    上一篇文章我写了tapable的基本用法,我们知道他是一个增强版版的发布订阅模式,本文想来学习下他的源码.tapable的源码我读了一下,发现他的抽象程度比较高,直接扎进去反而会让人云里雾里的,所以本 ...

  8. crx 文件安装 如何安装 Chrome插件

          Chrome 67 版本(大概2018.06.06的更新包)开始,插件已经无法离线安装啦,也就是自己无法使用crx文件安装插件,   而只能从chrome.google.com/webst ...

  9. 敏捷史话(十一):敏捷宣言“间谍”——Steve Mellor

    Steve Mellor 是敏捷宣言的签署人之一,他自称是作为" 间谍"去参加雪鸟会议的. 起初收到会议邀请时,Steve 非常惊讶,因为他所做的工作一直都是关于建模方面的,很少将 ...

  10. Java学习笔记--异常机制

    简介 在实际的程序运行过程中,用户并不一定完全按照程序员的所写的逻辑去执行程序,例如写的某个模块,要求输入数字,而用户却在键盘上输入字符串:要求打开某个文件,但是文件不存在或者格式不对:或者程序运行时 ...