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 ...
随机推荐
- ssh连接原理介绍( 无密码连接登录的原理)
SSH(Secure Shell)一种在不安全网络上提供安全远程登录及其它安全网络服务的协议.由客户端和服务端的软件组成的,有两个不兼容的版本分别是:1.x和2.x.(SSH 2.x的客户程序是不能 ...
- 《java入门第一季》之Calendar类小案例获取任意二月天数
import java.util.Calendar; import java.util.Scanner; /* * 获取任意一年的二月有多少天 * * 分析: * A:键盘录入任意的年份 * B:设置 ...
- Android高级控件(五)——如何打造一个企业级应用对话列表,以QQ,微信为例
Android高级控件(五)--如何打造一个企业级应用对话列表,以QQ,微信为例 看标题这么高大上,实际上,还是运用我么拿到listview去扩展,我们讲什么呢,就是研究一下QQ,微信的这种对话列表, ...
- Mahout 系列之----共轭梯度
无预处理共轭梯度 要求解线性方程组 ,稳定双共轭梯度法从初始解 开始按以下步骤迭代: 任意选择向量 使得 ,例如, 对 若 足够精确则退出 预处理共轭梯度 预处理通常被用来加速迭代方法的收敛.要使用预 ...
- Eclipse集成Android_NDK
Eclipse集成Android NDK说明 2 为什么要用NDK? 以下内容引用自<Pro Android Games> Some Java develo ...
- 【Matlab编程】Matlab及Java小时钟
一年前曾经用matlab的gui做了一个时钟,由于是直接用GUIDE和ActiveX控件写的,程序虽说有许多行,大多数都是自动生成的,自己写的只有十几行而已.闲着没事,就耗费了下午的时间用matlab ...
- OpenCV 实现颜色直方图
颜色直方图是在许多图像检索系统中被广泛采用的颜色特征.它所描述的是不同色彩在整幅图像中所占的比例,而并不关心每种色彩所处的空间位置,即无法描述图像中的对象或物体.颜色直方图特别适于描述那些难以进行自动 ...
- netstat 的10个基本用法(转)
本文转载自一译作. *注:netstat即network state缩写. Netstat 简介 Netstat 是一款命令行工具,可用于列出系统上所有的网络套接字连接情况,包括 tcp, udp 以 ...
- 中文注释 MariaDB my.cnf 大型服务器配置模板
文件如下所示,请根据需要进行修改: 翻译日期: 2014年5月22日 翻译人员: 铁锚 # /usr/share/mysql/my-huge.cnf # MariaDB 配置文件 示例模板(huge, ...
- Oracle rownum 分页, 排序
Oracle rownum 分页, 排序 什么是rownum, rownum的生成, rownum相关的符号操作 Rownum是oracle生成结果集时得到的一个伪列, 按照读出行的顺序, 第一条ro ...