事件驱动
来源:互联网 发布:sql server 触发器 编辑:程序博客网 时间:2024/05/23 23:25
事件驱动模型
事件驱动模型要素(what)
- 事件
- 事件源(生产者)
- 注册中心(事件通道)
- 侦听器(接受者)
事件驱动模型示意图
观察者模式
观察者设计模式涉及到两种角色:主题(Subject )和观察者(Observer )
事件驱动编程应用场景
- js页面开发
- Zookeeper开发
- GUI开发(awt/swing)
- Spring开发
事件驱动编程优点
- 无耦合的关联:事件发布者和事件订阅者预先无需知道彼此的存在。
- 异步消息传递:业务逻辑可以随事件同时发生。
- 多对多的交互:一个或多个事件会影响一个或多个订阅者。
- 基于事件的控制流程:当应用程序响应发生的事件时,应用程序流程非常自然。
Java事件编程技术方案
- Java 提供的观察者抽象
- java.util.Observable
- java.util.Observer
- Java 提供的事件驱动模型
- java.util.EventListener
- spring 事件驱动模型
- 分布式事件驱动模型
- 队列(jms)
- 发布/订阅(jms、zookeeper)
Spring 事件驱动模型要素
事件驱动模型要素
- 事件:org.springframework.context.ApplicationEvent
- 事件源(生产者): applicationContext.publishEvent(event)
- 侦听器(接受者): org.springframework.context.ApplicationListener
- 注册中心(事件通道): org.springframework.context.event.SimpleApplicationEventMulticaster
案例
航班案例
请求预定航班 –> 写入航班表 –> 发送提醒短信 –> 发送提醒邮件 –> 预定航班结束
写入航班表是最重要的业务 如果和后面两个次要的业务耦合在一次 那么短信服务出错和邮件服务出错都会使得事务回滚 航班定制失败 这是不可取的
改进
代码
事件(订阅航班)
import org.springframework.context.ApplicationEvent;public class FlightOrderEvent extends ApplicationEvent { private String fcode; private int user; public String getFcode() { return fcode; } public void setFcode(String fcode) { this.fcode = fcode; } public int getUser() { return user; } public void setUser(int user) { this.user = user; } public FlightOrderEvent(Object source, String fcode, int user) { super(source); this.fcode = fcode; this.user = user; }}
侦听器(接受者)
import javax.annotation.Resource;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.context.ApplicationListener;import org.springframework.stereotype.Service;import com.dongnao.event.entity.Email;import com.dongnao.event.service.EmailService;@Servicepublic class FilghtOrderEmailHandler implements ApplicationListener<FlightOrderEvent> { @Resource private EmailService es; private static final Logger logger = LoggerFactory.getLogger(FilghtOrderEmailHandler.class); @Override public void onApplicationEvent(FlightOrderEvent event) { // 调用邮件服务 logger.info("===================捕获预订航线信息,email开始处理=================="); Email email = new Email("系统", String.valueOf(event.getUser()), "预定航班成功", "您预订航班成功,航班号:"+event.getFcode()); es.sendMail(email); logger.info("===================捕获预订航线信息,email已处理=================="); }}
import java.util.Date;import javax.annotation.Resource;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.context.ApplicationListener;import org.springframework.stereotype.Service;import com.dongnao.event.entity.TMsg;import com.dongnao.event.service.MsgService;@Servicepublic class FilghtOrderMsgHandler implements ApplicationListener<FlightOrderEvent> { @Resource private MsgService ms; private static final Logger logger = LoggerFactory.getLogger(FilghtOrderMsgHandler.class); @Override public void onApplicationEvent(FlightOrderEvent event) { logger.info("===================捕获预订航线信息,msg开始处理=================="); //写入短信表 TMsg msg = new TMsg(); msg.setContent("您预订航班成功,航班号:"+event.getFcode()); msg.setCreatetime(new Date()); msg.setPhone("15577882500"); msg.setUser(event.getUser()); ms.addMsg(msg); logger.info("===================捕获预订航线信息,msg已处理=================="); }}
事件源(生产者)
import java.util.Date;import javax.annotation.Resource;import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import com.dongnao.event.entity.TFlight;import com.dongnao.event.event.FlightOrderEvent;import com.dongnao.event.mapper.TFlightMapper;import com.dongnao.event.service.FlightService;@Servicepublic class FlightServiceImpl implements FlightService,ApplicationContextAware { @Resource private TFlightMapper mapper; private ApplicationContext applicationContext; @Transactional @Override public void orderFlight(int user, String fcode) { //写入航班表 TFlight flight = new TFlight(); flight.setFcode(fcode); flight.setOrdertime(new Date()); flight.setUser(user); mapper.insert(flight); applicationContext.publishEvent(new FlightOrderEvent(this, fcode, user)); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext=applicationContext; }}
运行后发先如果邮件服务或者短信服务抛出异常 那么事物依然会回滚 原因是上面代码只做到了代码解耦并没有做到线程解耦 需在applicationContext.xml中配置如下:
<!-- 异步事件处理 --><bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster"> <!-- 注入任务执行器 这样就实现了异步调用(缺点是全局的,要么全部异步,要么全部同步(删除这个属性即是同步)) --> <property name="taskExecutor" ref="coreTaskExecutor" /></bean><bean id="coreTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="10" /> <property name="maxPoolSize" value="20" /> <property name="queueCapacity" value="25" /> <property name="threadNamePrefix" value="dongnao-CoreTaskExecutor" /></bean>
阅读全文
0 0
- 事件驱动
- 事件驱动
- 事件驱动
- 事件驱动
- 事件驱动
- 事件驱动
- 事件驱动
- 事件驱动
- 事件驱动
- 事件驱动
- 事件驱动VS消息驱动
- 事件驱动及事件处理
- 事件驱动及事件处理
- javascript事件驱动框架
- .net事件驱动实例
- 事件驱动之我见
- javaScript--事件驱动
- javascript 事件驱动杂谈
- C# 类型转换方法
- Codeforces 854 A. Fraction 水题
- PAT 1093. Count PAT's (25)
- 学习java之前
- PHP之变量类型
- 事件驱动
- 射频MIPI RFFE 全新MIPI RFFE標準協助RF前端邁向統一
- 3255:十进制到六进制
- Web
- 安卓andFix热修复
- 最新阿里云短信服务接口类【亲测成功】
- C#中Form的使用
- python mysql
- .NET(C#)生成随机姓名,随机汉字的产生