基于 观察者模式设置监听 || 及使用 listener监听实现,处理多渠道消息通知(短信+邮箱+公众号消息推送等)

观察者描述

1、观察者模式基本概念

一个对象状态改变,通知给其他所有的对象

2、观察者模式的应用场景

Zk的事件监听、分布式配置中心刷新配置文件、业务中群发不同渠道消息

在这里插入图片描述

一、使用 观察者模式设置监听

使用 观察者模式 是异步执行的多渠道消息通知(短信+邮箱+公众号消息推送等)

1、 SpringUtils 工具类

/**
 * SpringUtils 工具类
 */
@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext = null;

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static <T> T getBean(String beanId) {
        return (T) applicationContext.getBean(beanId);
    }

    public static <T> T getBean(Class<T> requiredType) {
        return (T) applicationContext.getBean(requiredType);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }
}

2、创建观察者接口

/**
 * 观察者接口
 */
public interface ObServer {

    void sendMsg(JSONObject jsonObject);
}

3、创建观察者一

@Component
@Slf4j
public class EmailObServer implements ObServer {
    @Override
    public void sendMsg(JSONObject jsonObject) {
        log.info("使用观察者发送邮件");
    }
}

4、创建观察者二

@Slf4j
@Component
public class SMSObServer implements ObServer {
@Override
public void sendMsg(JSONObject jsonObject) {
log.info(“使用观察者发送短信”);
}
}

5、所有、观察者容器


import com.alibaba.fastjson.JSONObject;
import com.xijia.xj.observer.ObServer;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
 * 观察者容器, listObServer = 所有的观察类
 * @author wangsong
 * @mail [email protected]
 * @date 2020/9/2 0002 21:22
 * @version 1.0.0
 */
@Component
public class XjSubject {

    /**
     * 类型 ObServer
     */
    private List<ObServer> listObServer = new ArrayList<>();
    /**
     * 线程池
     */
    private ExecutorService executorService;


    public XjSubject() {
        executorService = Executors.newFixedThreadPool(10);
    }

    /**
     * 新增ObServer
     *
     * @param obServer
     */
    public void addObServer(ObServer obServer) {
        listObServer.add(obServer);
    }

    /**
     * 通知给所有的观察者,遍历执行所有观察者的方法
     *
     * @param jsonObject
     */
    public void notifyObServer(JSONObject jsonObject) {
        for (ObServer obServer : listObServer) {
            // 单独开启线程异步通知
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    obServer.sendMsg(jsonObject);
                }
            });
        }
    }
}

6、自动注册所有观察者 到 观察者容器中

import com.xijia.xj.config.SpringUtils;
import com.xijia.xj.observer.ObServer;
import com.xijia.xj.observer.subject.XjSubject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.Map;
/**
 * 项目启动后需要 执行的一些方法 -->  注册观察者, 当我们的SpringBoot启动成功的时候,注册我们的SMSObServer
 * @author wangsong
 * @mail [email protected]
 * @date 2020/9/2 0002 21:27
 * @version 1.0.0
 */
@Component
public class InitService implements ApplicationRunner {


    @Autowired
    private XjSubject xjSubject;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        /**
         * 自动注册我们观察者
         * 1.使用Spring获取该ObServer下有那些bean对象
         * 2.直接注添加到集合中
         */
        //根据接口类型返回相应的所有bean
        Map<String, ObServer> map = SpringUtils.getApplicationContext().getBeansOfType(ObServer.class);
        for (String key : map.keySet()) {
            ObServer obServer = map.get(key);
            xjSubject.addObServer(obServer);
        }
    }
}

7、使用观察者模式

@RestController
@Slf4j
public class OrderService {
   
    @Autowired
    private XjSubject xjSubject;

    @RequestMapping("/addOrder")
    public String addOrder() {
        log.info("1.调用数据库下单订单代码:");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sms", "1865891111");
        jsonObject.put("email", "[email protected]");
        xjSubject.notifyObServer(jsonObject);
        return "success";
    }
  }

8、执行效果

在这里插入图片描述

二、使用 spring 的 Listener 监听

注意 spring 的 Listener 是同步执行的,不支持@Async 异步注解

1、创建监听传递的,参数类

package com.xijia.spring.entity;

import org.springframework.context.ApplicationEvent;

public class UserMessageEntity extends ApplicationEvent {
    private String email;
    private String phone;
    private String userId;

    /**
     * Create a new ApplicationEvent.
     *
     * @param source the object on which the event initially occurred (never {@code null})
     */
    public UserMessageEntity(Object source) {
        super(source);
    }

    public UserMessageEntity(Object source, String email, String phone) {
        super(source);
        this.email = email;
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "email:" + email + ",phone:" + phone;
    }
}

2、创建监听1(观察者1)

/**
 * 监听发送邮件
 */
@Component
public class EmailListener implements ApplicationListener<UserMessageEntity> {
    /**
     * 监听的方法
     *
     * @param event
     */
    @Override
    @Async
    public void onApplicationEvent(UserMessageEntity event) {
        System.out.println(Thread.currentThread().getName() +"  邮件:" + event.toString());
    }
}

3、创建监听2(观察者2)

/**
 * 监听发送邮件
 */
@Component
public class SmSListener implements ApplicationListener<UserMessageEntity> {
    /**
     * 监听的方法
     *
     * @param event
     */
    @Override
    @Async
    public void onApplicationEvent(UserMessageEntity event) {
        System.out.println(Thread.currentThread().getName() + "  短信:" + event.toString());
    }
}

4、使用Listener 监听


@RestController
@Slf4j
public class OrderService {

    @RequestMapping("/addOrder2")
    public String addOrder2() {
       
        log.info("1.调用数据库下单订单代码:");
        UserMessageEntity userMessageEntity = new UserMessageEntity(this, "[email protected]", "1865891111");
        applicationEventPublisher.publishEvent(userMessageEntity);
        return "success";
    }
}

5、执行效果

在这里插入图片描述

  • 以上部分内容出自于蚂蚁课堂 http://www.mayikt.com/

  • 个人开源项目(通用后台管理系统)–> https://gitee.com/wslxm/spring-boot-plus2 , 喜欢的可以看看

  • 本文到此结束,如果觉得有用,动动小手点赞或关注一下呗,将不定时持续更新更多的内容…,感谢大家的观看!

猜你喜欢

转载自blog.csdn.net/qq_41463655/article/details/108371356