前言

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

    /**
* 用户注册
*/
@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. SSM-员工管理项目实战-CRUD-增删改查

    SSM-CRUD 一.项目简介 主界面演示 功能点 分页 数据校验 ajax Rest 风格的 URI 技术点 基础框架 - ssm(Spring + SpringMVC + MyBatis) 数据库 ...

  2. 了解 Vue 的 Compsition API

    在这篇文章中,我将讲讲 Vue 的 Composition API 为什么比之前的 Options API 要好,以及它是如何工作的. Options API 有什么问题 首先,这里不是要大家放弃 O ...

  3. DB性能瓶颈分析思路

    在性能分析过程中,经常遇到性能瓶颈出现在SQL的情况,此类问题通常可以分为两大类场景,一是SQL自身性能差导致的慢,如索引缺失.索引失效.统计信息不准确.SQL过于复杂等:二是由于外部原因等待导致的S ...

  4. BUAAOO第一单元代码分析

    1.HomeWork1 思路 一个主类用于字符串得操作, 一个Poly类用于对一个多项式进行抽象,用Arraylist来对term进行封装.内部含有求导方法,添加并合并同类项的方法,toString方 ...

  5. Java代码度量分析工具:DesigniteJava简介

    前言 在Java面向对象课程的学习过程中,我们需要使用度量工具来分析自己程序的代码结构.受OO课程组以及前辈们博客提醒,笔者找到了DesigniteJava这款软件,现对此软件进行简单的说明. 一.D ...

  6. php添加excel更新数据表数据

    公司有个需求,是用excel更新数据的,把错误的行列放到一个数组返回出来,正常的数据则插入,且返回数量 1.先需要引入phpspreadsheet,这里使用composer 安装 composer r ...

  7. Leedcode算法专题训练(搜索)

    BFS 广度优先搜索一层一层地进行遍历,每层遍历都是以上一层遍历的结果作为起点,遍历一个距离能访问到的所有节点.需要注意的是,遍历过的节点不能再次被遍历. 第一层: 0 -> {6,2,1,5} ...

  8. 关于Kotlin中日志的使用方法

    1 引言 想必学过Java的人都知道一个@Slf4j使用得多么的舒服: @Slf4j public class TestController{ @GetMapping("/test" ...

  9. 本地+分布式Hadoop完整搭建过程

    1 概述 Hadoop在大数据技术体系中极为重要,被誉为是改变世界的7个Java项目之一(剩下6个是Junit.Eclipse.Spring.Solr.HudsonAndJenkins.Android ...

  10. 整合Atomikos、Quartz、Postgresql的踩坑日记

    前言 由于业务需要,在单体Spring Boot项目中需要引入分布式事务,来保证单体应用连接的多个数据源的事务统一. 而说到分布式事务,小伙伴们肯定会想到阿里的Seata,阿里Seata强大的AT模式 ...