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());
	}
}

posted @ 2018-10-15 23:41  mysgk  阅读(1269)  评论(2编辑  收藏  举报