观察者描述
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 1720696548@qq.com
* @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 1720696548@qq.com
* @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", "644064779@qq.com");
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, "644064779@qq.com", "1865891111");
applicationEventPublisher.publishEvent(userMessageEntity);
return "success";
}
}
5、执行效果
以上部分内容出自于蚂蚁课堂 http://www.mayikt.com/
个人开源项目(通用后台管理系统)–> https://gitee.com/wslxm/spring-boot-plus2 , 喜欢的可以看看
本文到此结束,如果觉得有用,动动小手点赞或关注一下呗,将不定时持续更新更多的内容…,感谢大家的观看!