请出主角:Spring当中的事件机制
没错,本节主要讲的是Spring中事件机制:ApplicationEventPublisher,实现监听ApplicationEvent,最后利用事件通知实现通知实现异步操作
1、为什么要实现异步操作
- 在微服务的情况下,多个服务互相调用,及其耗时,当我们不需要此操作返回时,可以异步执行,调用接口,该接口快速返回,减少接口响应时长。
- 代码逻辑性清晰,对于需要多个异步操作的可以实现事件的统一管理,不用创建线程池,减少资源的消耗
2、编程过程中有哪些可以去异步执行的
- 所有耗时、且不需要返回的函数
- 比如记录日志操作、发送邮件、短信等操作
代码展示(先实战、后原理)
假如我们现在有一个需求,购买会员操作!先来分析具体步骤:
1、在会员用户列表添加该用户(代表该用户已经具有会员标示)
2、发送具体会员的权益
3、给用户添加积分操作
4、发送短信通知
假如有上四步,那么我们可以将发送短信通知作为异步操作。
第一步,创建事件
public class SendMessageEvent extends ApplicationEvent {
private SendMessageEventDto sendMessageEventDto;
public SendMessageEvent(Object source) {
super(source);
}
public SendMessageEvent(Object source,SendMessageEventDto dto){
super(source);
this.sendMessageEventDto = dto;
}
public SendMessageEventDto getDto(){
return sendMessageEventDto;
}
public void setDto(SendMessageEventDto dto){
this.sendMessageEventDto = dto;
}
public class SendMessageEventDto{
/**
* 手机号
*/
private Integer userId;
/**
* 手机号
*/
private String mobile;
/**
* 短信模板参数数据体
*/
private String data;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
}
}
上面代码中首先定义发送短信的一个实体(SendMessageEventDto),将这个实体交给定义的事件管理(SendMessageEvent),该事件继承spring的ApplicationEvent
第二步,将事件通过spring发布,由spring监听该事件
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
/**
* 组装数据体异步发送短信
* @param mobile 手机号
* @param userId 用户ID
* @param jsonObject 短信所需参数
*/
public void publishMessage(String mobile,Integer userId,JSONObject jsonObject){
SendMessageEvent event = new SendMessageEvent(this);
SendMessageEvent.SendMessageEventDto dto = event.new SendMessageEventDto();
dto.setData(jsonObject.toString()); //具体业务的数据体
dto.setMobile(mobile);
dto.setUserId(userId);
event.setDto(dto);
//将事件交给spring监听
applicationEventPublisher.publishEvent(event);
}
第三步,让具体业务持有该事件,并设置被监听状态
public interface SendMessageEventListener {
//发送短信
void sendMessage(SendMessageEvent sendMessageEvent);
}
@Component
public class SendMessageEventListenerImpl implements SendMessageEventListener {
private Logger logger = LoggerFactory.getLogger(SendMessageEventListenerImpl.class);
@Autowired
private MiniProgramClient miniProgramClient;
@Override
@Async
@EventListener
public void sendMessage(SendMessageEvent sendMessageEvent) {
try {
SendMessageEvent.SendMessageEventDto dto = sendMessageEvent.getDto();
logger.error("发送短信通知开始 -> 数据体为 -> "+ JSON.toJSONString(dto));
MarketMessageDto messageDto = new MarketMessageDto();
messageDto.setUserId(dto.getUserId());
messageDto.setData(dto.getData());
messageDto.setMobile(dto.getMobile());
//调用短信服务,发送短信
miniProgramClient.sendMarketMsg(messageDto);
}catch (Exception e){
e.getMessage();
e.printStackTrace();
}
}
}
这里特别注意的是,必须在需要被监听的方法上加上 @EventListener, 然后开启异步 @Async
演示调用,大功告成
public static void main(String[] args) {
//创建会员逻辑开始
//1、创建会员用户
//2、发送会员权益
//3、给用户添加积分
//4发送短信
publishMessage("176********",7465388,具体业务参数的json)
//返回结果
return "开通会员成功";
}
OK,到这里就大功告成了,整体流程就是这样,这样当执行到给用户添加积分之后,就可直接返回成功,无须等待发送短信操作。
特别注意:在springBoot项目中使用的话,需要在启动类当中加入注解@EnableAsync