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());
    }
}
相關文章
相關標籤/搜索