請出主角: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
弦外之音
如果感覺對你有幫助的話,歡迎,點贊、分享加關注,后續我會輸出更多技術干貨,我們共同進步!
作者:蘇世_
鏈接:
https://juejin.cn/post/6985049438540529694
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。