Spring Boot 事件和监听
Application Events and Listeners
1、自定义事件和监听
1.1、定义事件
package com.cjs.boot.event; import lombok.Data;
import org.springframework.context.ApplicationEvent; @Data
public class BlackListEvent extends ApplicationEvent { private String address; public BlackListEvent(Object source, String address) {
super(source);
this.address = address;
}
}
1.2、定义监听
package com.cjs.boot.event; import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component; public class BlackListListener implements ApplicationListener<BlackListEvent> { @Override
public void onApplicationEvent(BlackListEvent event) {
System.out.println("监听到BlackListEvent事件: " + event.getAddress());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1.3、注册监听
package com.cjs.boot; import com.cjs.boot.event.BlackListListener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication
public class CjsSpringbootExampleApplication { public static void main(String[] args) { SpringApplication springApplication = new SpringApplication(CjsSpringbootExampleApplication.class);
springApplication.addListeners(new BlackListListener());
springApplication.run(args); }
1.4、发布事件
package com.cjs.boot.controller; import com.cjs.boot.event.BlackListEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
@RequestMapping("/activity")
public class ActivityController { // @Autowired
// private ApplicationEventPublisher publisher; @Autowired
private ApplicationContext publisher; @GetMapping("/sayHello.json")
public void sayHello() { /**
* You may register as many event listeners as you wish, but note that by default event listeners receive events synchronously.
* This means the publishEvent() method blocks until all listeners have finished processing the event.
*/ BlackListEvent event = new BlackListEvent(this, "abc@126.com");
publisher.publishEvent(event);
System.out.println("事件发布成功");
} }
2、基于注解的事件监听
package com.cjs.boot.event; import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component; @Component
public class BlackListListener { @EventListener
public void processBlackListEvent(BlackListEvent event) {
System.out.println(123);
}
} --- package com.cjs.boot; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class CjsSpringbootExampleApplication { public static void main(String[] args) {
SpringApplication.run(CjsSpringbootExampleApplication.class, args);
} }
3、异步监听
@EventListener
@Async
public void processBlackListEvent(BlackListEvent event) {
// BlackListEvent is processed in a separate thread
}
4、应用
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger; /**
* 批量送券
*/
@Slf4j
@Component
public class BatchSendCouponListener { @Autowired
private CouponPresentLogService couponPresentLogService; @Async
@EventListener
public void processBatchSendCouponEvent(BatchSendCouponEvent batchSendCouponEvent) {
Long cpId = batchSendCouponEvent.getCouponPresentId();
log.info("收到BatchSendCouponEvent, cpId={}", cpId);
List<CouponPresentLogEntity> list = couponPresentLogService.selectByPid(cpId); handle(cpId, list, 0);
} private void handle(Long cpId, List<CouponPresentLogEntity> list, int times) {
if (times >= 2) {
log.info("超过重试次数退出, cpId: {}, 剩余: {}", cpId, list.size());
return;
} List<Future<CouponPresentLogEntity>> futureList = new ArrayList<>(); for (CouponPresentLogEntity entity : list) {
futureList.add(couponPresentLogService.present(entity));
} AtomicInteger count = new AtomicInteger(0);
// 收集失败的
List<CouponPresentLogEntity> failList = new ArrayList<>();
for (Future<CouponPresentLogEntity> future : futureList) {
try {
CouponPresentLogEntity couponPresentLogEntity = future.get();
if (couponPresentLogEntity.getStatus() != PresentStatusEnum.SUCCESS.getType().intValue()) {
failList.add(couponPresentLogEntity);
}
count.getAndIncrement();
if (count.intValue() >= list.size()) {
List<CouponPresentLogEntity> failPresentLogList = couponPresentLogService.selectFailLogByPid(cpId);
if (null != failPresentLogList && failPresentLogList.size() > 0) {
times++;
log.info("第{}次重试, CPID: {}, 总计: {}, 失败: {}", times, cpId, list.size(), failPresentLogList.size());
handle(cpId, failPresentLogList, times);
}
}
} catch (InterruptedException e) {
log.error(e.getMessage(), e);
} catch (ExecutionException e) {
log.error(e.getMessage(), e);
}
}
} }
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service; import javax.annotation.Resource;
import java.util.concurrent.*; @Service
@Slf4j
public class CouponPresentLogServiceImpl implements CouponPresentLogService { @Autowired
private CouponPresentLogDao couponPresentLogDao;
@Resource
private CouponSendRpcService couponSendRpcService; @Async("myThreadPoolTaskExecutor")
@Override
public Future<CouponPresentLogEntity> present(CouponPresentLogEntity entity) {
try {
CouponBaseResponse rst = couponSendRpcService.send(entity.getUserId(), entity.getCouponBatchKey(), "1", entity.getVendorId());
if (null != rst && rst.isSuccess()) {
entity.setStatus(PresentStatusEnum.SUCCESS.getType());
entity.setFailureReason(PresentStatusEnum.SUCCESS.getName());
}else {
String reason = (null == rst) ? "响应异常" : rst.getMsg();
entity.setFailureReason(reason);
entity.setStatus(PresentStatusEnum.FAILURE.getType());
}
}catch (Exception ex) {
log.error(ex.getMessage(), ex);
entity.setFailureReason(ex.getMessage());
entity.setStatus(PresentStatusEnum.FAILURE.getType());
}
couponPresentLogDao.update(entity); return new AsyncResult<CouponPresentLogEntity>(entity);
} }
5、统计异步任务执行的进度
利用Future获取执行结果,比如上面的例子中,由于不是直接提交的任务,所以用AsyncResult来返回结果
上面的例子中,一个大任务,然后下面有许多子任务。在主任务中,统计各子任务的执行情况,是成功还是失败,然后统计成功多少,失败多少
也可以这样写:
@Autowired
ThreadPoolTaskExecutor taskExecutor; Future<Object> future = taskExecutor.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
return null;
}
});
Spring Boot 事件和监听的更多相关文章
- 【spring源码学习】spring的事件发布监听机制源码解析
[一]相关源代码类 (1)spring的事件发布监听机制的核心管理类:org.springframework.context.event.SimpleApplicationEventMulticast ...
- Spring笔记(7) - Spring的事件和监听机制
一.背景 事件机制作为一种编程机制,在很多开发语言中都提供了支持,同时许多开源框架的设计中都使用了事件机制,比如SpringFramework. 在 Java 语言中,Java 的事件机制参与者有3种 ...
- Spring Boot实现一个监听用户请求的拦截器
项目中需要监听用户具体的请求操作,便通过一个拦截器来监听,并继续相应的日志记录 项目构建与Spring Boot,Spring Boot实现一个拦截器很容易. Spring Boot的核心启动类继承W ...
- rabbitMq与spring boot搭配实现监听
在我前面有一篇博客说到了rabbitMq实现与zk类似的watch功能,但是那一篇博客没有代码实例,后面自己补了一个demo,便于理解.demo中主要利用spring boot的配置方式, 一.消费者 ...
- Spring boot设置启动监听端口
一.通过配置 修改application.properties 在属性文件中添加server.port=8000 二.直接看代码: @Controller @EnableAutoConfigurati ...
- Spring Boot(六)自定义事件及监听
事件及监听并不是SpringBoot的新功能,Spring框架早已提供了完善的事件监听机制,在Spring框架中实现事件监听的流程如下: 自定义事件,继承org.springframework.con ...
- 深入理解Spring的容器内事件发布监听机制
目录 1. 什么是事件监听机制 2. JDK中对事件监听机制的支持 2.1 基于JDK实现对任务执行结果的监听 3.Spring容器对事件监听机制的支持 3.1 基于Spring实现对任务执行结果的监 ...
- 【laravel】Eloquent 模型事件和监听方式
所有支持的模型事件 在 Eloquent 模型类上进行查询.插入.更新.删除操作时,会触发相应的模型事件,不管你有没有监听它们.这些事件包括: retrieved 获取到模型实例后触发 creatin ...
- uniapp仿h5+fire自定义事件触发监听
仿h5+fire自定义事件触发监听 uni-app调用 event.js 源码记录(点击查看) 1.js下载地址 [event.js](https://ext.dcloud.net.cn/plugin ...
随机推荐
- C++ Primer 有感(多重继承与虚继承)
1.多重继承的构造次序:基类构造函数按照基类构造函数在类派生列表中的出现次序调用,构造函数调用次序既不受构造函数初始化列表中出现的基类的影响,也不受基类在构造函数初始化列表中的出现次序的影响.2.在单 ...
- 如何获得mysql数据库的所有的列
命令行下直接用:descrbe 表名 hive也是一样的. 用查询: SELECT COLUMN_NAME FROM `information_schema`.`COLUMNS` where ` ...
- 认证模式之Basic模式
HTTP协议规范中有两种认证方式,一种是Basic认证,另外一种是Digest认证,这两种方式都属于无状态认证方式,所谓无状态即服务端都不会在会话中记录相关信息,客户端每次访问都需要将用户名和密码放置 ...
- [Java]数组排序-选择排序 冒泡排序 插入排序
1 选择排序 原理:a 将数组中的每个元素,与第一个元素比较 如果这个元素小于第一个元素, 就将这个 两个元素交换. b 每轮使用a的规则, 可以选择出 ...
- 一堆C++人找不出内存泄露
一堆C++人找不出内存泄露 内存泄露就像痔疮对于男人,对于C/C++程序员来说,是顽疾.尤其一堆C++人聚集在一起,准备把程序深处的虫子抓出来的时候,那景象是热火朝天,不亦乐乎. 突然,小白甲发布了一 ...
- Oracle中添加自动编号的序列
1. 创建表T_Test create table T_Test(id int ,address char(25), pay int); 2. 创建自增序列 create sequence SEQ_ ...
- "《算法导论》之‘线性表’":基于数组实现的单链表
对于单链表,我们大多时候会用指针来实现(可参考基于指针实现的单链表).现在我们就来看看怎么用数组来实现单链表. 1. 定义单链表中结点的数据结构 typedef int ElementType; cl ...
- Gradle 1.12用户指南翻译——第三十九章. IDEA 插件
本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- SharePoint WebPart 简单的读取列表内容的web部件
最近,自己也在学习写一些SharePoint的部件,也就是使用对象模型,下面,介绍一下自己刚刚写的小测试程序,不足之处,还请指正. 1. 新建项目 Vs2008 – 新建 – 项目 – 类库 – 输 ...
- php引用传值详解
php的引用(就是在变量或者函数 .对象等前面加上&符号) 在PHP 中引用的意思是:不同的名字访问同一个变量内容. 与C语言中的指针是有差别的.C语言中的指针里面存储的是变量的内容在内存中存 ...