springboot 中事件監聽模型的一種實現



前言: 事件監聽模型是一種常用的設計模式,在springboot 中我們如何實現呢?
首先我們要理解事件監聽中需要的幾個角色

  • 事件發布者 (即事件源)
  • 事件監聽者
  • 事件本身

廢話不多說直接上代碼

定義事件本身

事件本身需要繼承ApplicationEvent

package com.yxd;

import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationEvent;

public class DemoEvent extends ApplicationEvent{

	private String type;
	private List<Map> msg;
	
	public DemoEvent(Object object, String type ,List<Map> msg) {
		super(object);
		this.msg = msg;
		this.type = type;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public List<Map> getMsg() {
		return msg;
	}

	public void setMsg(List<Map> msg) {
		this.msg = msg;
	}

}

如圖:

定義事件源

事件源需要注入 **ApplicationContext **

package com.yxd;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class DemoPublisher {

	@Autowired
	ApplicationContext applicationContext;
	
	public void publish(DemoEvent event) {
		applicationContext.publishEvent(event);
	}
}

定義監聽者

監聽者有兩種實現

一、需要實現 ApplicationListener

package com.yxd;

import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class DemoListener1 implements ApplicationListener<DemoEvent> {

	@Override
	public void onApplicationEvent(DemoEvent event) {
		List<Map> msg = event.getMsg();
		String type = event.getType();
		System.out.println(" listener1接收到了 publisher 發送的消息 , 時間 "+ Time.getTime());
		System.out.println("listener1 : 類型 :" + type +", 消息內容: " + msg + ", 消息處理完畢! "+ Time.getTime());
	}
}

二、使用 @EventListener 注解

package com.yxd;

import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class DemoListener2 {

	@EventListener
	public void onDemoEvent(DemoEvent demoEvent) {
		System.out.println(" listener2 通過注解接收到了 publisher 發送的消息 , 時間 "+ Time.getTime());
		List<Map> msg = demoEvent.getMsg();
		String type = demoEvent.getType();
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		System.out.println("listener2 : 類型 :" + type +", 消息內容: " + msg + ", 消息處理完畢! "+ Time.getTime());
	}
}

此處我們還需要注意一點,此處多個監聽是同步執行的(阻塞),一般情況下我們發布一個事件,是不關心誰來處理,以及處理結果的,所以我們還需要加上異步的注解

package com.yxd;

import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;


@Component
public class DemoListener3 implements ApplicationListener<DemoEvent> {

	@Override
	@Async
	public void onApplicationEvent(DemoEvent event) {
		System.out.println(" listener3 接收到了 publisher 發送的消息 , 時間 "+ Time.getTime());
		List<Map> msg = event.getMsg();
		String type = event.getType();
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("listener3 異步執行:類型 :" + type +", 消息內容: " + msg+ ", 消息處理完畢! "+ Time.getTime());
		
	}
}

測試

package com.yxd;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@EnableAsync
@SpringBootApplication
@RestController
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

	@Autowired
	DemoPublisher demoPublisher;

	@RequestMapping("testListener")
	public String testListener() {
		ArrayList<Map> list = new ArrayList<>();		
		HashMap<String, String> m1 =  new HashMap<>();
		m1.put("1", "2");
		HashMap<String, String> m2 =  new HashMap<>();
		m2.put("3", "4");
		HashMap<String, String> m3 =  new HashMap<>();
		m3.put("5", "6");		
		list.add(m1);
		list.add(m2);
		list.add(m3);
		System.out.println("開始發布消息: " + Time.getTime());
		demoPublisher.publish(new DemoEvent(this,"測試消息",list));
		System.out.println("消息發布結束: " + Time.getTime());
		return "消息發布成功";
	}
}

我們訪問接口

三個監聽者都得到了消息。。
但是 listener2 通過注解 先得到了消息,延時2秒后,listener1 才得到消息,listener1 處理完后,主線程繼續執行,同時listener3 開始接收到消息,開啟了一個異步任務,3秒后執行結束

項目結構

最后附上Time

package com.yxd;

import java.text.SimpleDateFormat;
import java.util.Date;


public class Time {

	public static String getTime() {
		return new SimpleDateFormat("HH:mm:ss").format(new Date());
	}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM