springboot 中事件监听模型的一种实现


前言: 事件监听模型是一种经常使用的设计模式,在springboot 中咱们如何实现呢?
首先咱们要理解事件监听中须要的几个角色web

  • 事件发布者 (即事件源)
  • 事件监听者
  • 事件自己

废话很少说直接上代码spring

定义事件自己

事件自己须要继承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;
    }

}

如图:
springboot

定义事件源

事件源须要注入 ApplicationContext app

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

定义监听者

监听者有两种实现异步

1、须要实现 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());
    }
}

2、使用 @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());
    }
}

此处咱们还须要注意一点,此处多个监听是同步执行的(阻塞),通常状况下咱们发布一个事件,是不关心谁来处理,以及处理结果的,因此咱们还须要加上异步的注解ide

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秒后执行结束this

项目结构

最后附上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());
    }
}
相关文章
相关标签/搜索