• 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());
    	}
    }
    
    
  • 相关阅读:
    mysql常见的优化方法
    Mac 怎么通过自带终端连接linux服务器
    基于 appium 的 UI 自动化测试
    sourcetree在mac上的使用
    mac下git安装和使用
    mac 上更改环境变量
    Mac环境下svn的使用
    jira常用配置
    influxDB基本操作
    Collectd 和 InfluxDB 的部署和使用
  • 原文地址:https://www.cnblogs.com/mysgk/p/9795484.html
Copyright © 2020-2023  润新知