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 ...
随机推荐
- javascript之JSON小案例,实现添加数据与清楚数据
对json应用给出一个小案例,加深一些理解: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" & ...
- MySQL学习笔记_5_SQL语言的设计与编写(上)
SQL语言的设计与编写(上) 一.SQL语句分类 数据定义语言(DDL): 用于定义和管理数据对象,包括数据库.数据表.视图.索引等.例如:CREATE.DROP.ALTER等语句. 数据操作语言(D ...
- 网站开发进阶(二十九)HTML特殊转义字符
HTML特殊转义字符 参考文献 http://tool.oschina.net/commons?type=2 美文美图
- 18_Android中Service的生命周期,远程服务,绑定远程服务,aidl服务调用,综合服务案例,编写一个应用程序调用远程支付宝远程服务场景
============================================================================ 服务的生命周期: 一.采用start的方式开始 ...
- 取消选中单选框radio的三种方式
作者: 铁锚 日期: 2013年12月21日 本文提供了三种取消选中radio的方式,代码示例如下: 本文依赖于jQuery,其中第一种,第二种方式是使用jQuery实现的,第三种方式是基于JS和DO ...
- 用Zmq实现网关与游戏服全互连
用Zmq实现网关与游戏服全互连(金庆的专栏)Zeromq无需bind, connect次序,可以在对方bind之前就connect, 可实现服务器以任意顺序启动.Zmq有自动重连功能,可实现服务器故障 ...
- 深入认识AsyncTask
1.概述 在android开发中是采用单线程模型,主线程通常称为UI线程,由于UI线程的操作不是线程安全的,因此android规定有关更新界面的操作必须在主线程中进行,其他线程直接报错. 如果我们把所 ...
- leetcode(58)-Range Sum Query - Immutable
题目: Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclu ...
- SQLSERVER 性能优化之Perfmon指标
Perfmon是Windows系统性能监视程序.用于监视CPU使用率.内存使用率.硬盘读写速度.网络速度等. Processor/%Privileged Time阀值:如果数值持续大于75%就表示存在 ...
- Spring的事务 之 9.1 数据库事务概述 ——跟我学spring3
9.1 数据库事务概述 事务首先是一系列操作组成的工作单元,该工作单元内的操作是不可分割的,即要么所有操作都做,要么所有操作都不做,这就是事务. 事务必需满足ACID(原子性.一致性.隔离性和持久性 ...