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 ...
随机推荐
- epoll通俗讲解
转载地址:http://yaocoder.blog.51cto.com/2668309/888374 首先我们来定义流的概念,一个流可以是文件,socket,pipe等等可以进行I/O ...
- javascript之DOM编程通过html元素的标签属性找节点
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 【Android 应用开发】Android 平台 HTTP网速测试 案例 API 分析
作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/25996817 工信部规定的网速测试标准 : 除普通网页测速 ...
- HTML5进阶(二)HBuilder实现软件自动升级
HBuilder实现软件自动升级 前言 移动APP开发好后需要实现软件自动升级功能,经过一番搜索,发现HBuilder具有"App资源在线升级更新"的功能,遂研究之. 经过一番测试 ...
- (八)喜马拉雅Demo引出的细节(代理模式和图片缩放)
喜玛拉雅是一款电台APP,界面非常美观,通过模仿这一APP学习到很多细节. 1.图片导入后有些框内不全如何补全: 寻常的办法是再准备一张图片拖入,比较好的办法是右击已经导入的图片选择Show in F ...
- iOS中UITableView分割线左侧顶齐
iOS 7开始UITableView的分割线不在从左侧边界开始了,而是默认空出了一段距离. 如果想要使用默认的分割线而且还要从左侧边界开始的话,有几种解决方式: 1.在tableView的代理方法中设 ...
- Java-ServletRequestWrapper
/** * * Provides a convenient implementation of the ServletRequest interface that * can be subclasse ...
- mahout系列----Dirichlet 分布
Dirichlet分布可以看做是分布之上的分布.如何理解这句话,我们可以先举个例子:假设我们有一个骰子,其有六面,分别为{1,2,3,4,5,6}.现在我们做了10000次投掷的实验,得到的实验结果是 ...
- objective-c中@autoreleasepool的用法
objc中关于自动释放池,有两种语法,一种old-fashioned是: NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //d ...
- The 7th tip of DB Query Analyzer
The 7th tip of DB Query Analyzer MA Gen feng ( Guangdong Unitoll Services incorporated, Gu ...