设为首页 收藏本站
查看: 318|回复: 0

[经验分享] tomcat事件处理机制

[复制链接]

尚未签到

发表于 2017-1-24 08:49:44 | 显示全部楼层 |阅读模式
  最近在阅读“how tomcat works”这本书,结合tomcat7的源码进行学习。对于学习的收获,将通过“tomcat学习系列”记录下来,和大家一起分享和交流,也算对自己学习的一种促进。闲话不多说,正文开始。
  Catalina内部由多个组件组成,启动时各个组件都需要启动,关闭时需要各个组件关闭。如何协作各个组件的初始化、启动、停止、销毁等的一致性,通过各组件实现Lifecycle这个接口来完成。各组件在启动、关闭等重要生命周期中,会发出事件通知,通知已注册的观察者做事件处理。
  一、主要类图
   DSC0000.jpg

  二、主要类介绍

  1)
Lifecycle


  Lifecycle定义了组件生命周期中的通用事件(START_EVENT、STOP_EVENT等)和接口(start、stop、destroy、addLifecycleListener、removeLifecycleListener等)。组件可以通过实现Lifecyecle接口,完成组建的重要生命周期实现和组建的观察者管理。

  2)LifecycleState

  定义了组件生命周期中的状态和状态对应的事件。当状态发生改变时,会发出相应事件,通知观察者进行处理。

  3)LifecycleBase

  Lifecycle接口的默认实现,实现init、start、stop、destroy等方法。对观察者的增加、查找和删除等操作会适配器方式,由组合的LifecycleSupport实例来完成。

  4)LifecycleSupport

  观察者的实际管理类,实现观察者的注册、删除、查询、调用等操作。

  5)LifecycleListener

  生命周期的观察者,定义了观察者的事件处理接口lifecycleEvent(LifecycleEvent
event)。


  6)ServerLifecycleListener

  实际的观察者,实现了事件处理接口。

  7)LifecycleEvent

  观察者使用的参数,它封装了事件来源、事件类型和事件数据,使得观察者可以按事件来源和事件类型分类处理事件。

  三、生命周期重要过程

  1.
观察者注册


  观察者的注册可以通过xml方式配置,也可以通过直接调用Lifecycle的观察者添加方法。server.xml中观察者配置如下:

  

<Server port="8005" shutdown="SHUTDOWN">  
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />  
<Listener className="org.apache.catalina.core.JasperListener" />  
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />  
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />  
...  
</Server>  
LifecycleSupport的观察者注册代码如下:
  

public final class LifecycleSupport {  
// 观察者数组  
private LifecycleListener listeners[] = new LifecycleListener[0];  
...  
public void addLifecycleListener(LifecycleListener listener) {  
synchronized (listenersLock) {  
LifecycleListener results[] =  
new LifecycleListener[listeners.length + 1];  
for (int i = 0; i < listeners.length; i++)  
results = listeners;  
results[listeners.length] = listener;  
listeners = results;  
}  
}  
}  
观察者是通过数组来维护,每次增加一个新的观察者,都需要将当前数组长度加1,将原来数组内容拷贝到新的数组中。对这里的设计我比较困惑,为什么采用这种数组扩容方式,这样每次增加新增观察者都需要数组拷贝,影响性能。可能的一个原因是,考虑到观察者数目少和新增的次数少,这种方式可以减少内存占用。
  2.
通知观察者

组件的生命周期中状态发生改变时,都会发出事件,通知观察者处理。下面以LifecycleBase中init()方法举例说明。

  

public abstract class LifecycleBase implements Lifecycle {  
private LifecycleSupport lifecycle = new LifecycleSupport(this);  
// 当前状态  
private volatile LifecycleState state = LifecycleState.NEW;  
public synchronized final void init() throws LifecycleException {  
if (!state.equals(LifecycleState.NEW)) {  
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);  
}  
// 状态转移到INITIALIZING,会发送事件  
setState(LifecycleState.INITIALIZING);  
initInternal();  
setState(LifecycleState.INITIALIZED);  
}  
protected synchronized void setState(LifecycleState state, Object data) {  
...  
this.state = state;  
// state为枚举类型,获取该枚举值对应的事件类型  
String lifecycleEvent = state.getLifecycleEvent();  
if (lifecycleEvent != null) {  
// 发起事件通知  
fireLifecycleEvent(lifecycleEvent, data);  
}  
}  
// 调用LifecycleSupport进行事件处理  
protected void fireLifecycleEvent(String type, Object data) {  
lifecycle.fireLifecycleEvent(type, data);  
}  
}  
LifecycleSupport中的事件处理方法如下:
  

public void fireLifecycleEvent(String type, Object data) {  
// 包装事件类型和数据  
LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);  
// 循环,通知所有观察者进行事件处理  
LifecycleListener interested[] = listeners;  
for (int i = 0; i < interested.length; i++)  
interested.lifecycleEvent(event);  
}  
3.
观察者事件处理

以ServerLifecycleListener为例,说明观察者事件处理过程。
  

public class ServerLifecycleListener
implements ContainerListener, LifecycleListener, PropertyChangeListener {
...
public void lifecycleEvent(LifecycleEvent event) {
Lifecycle lifecycle = event.getLifecycle();
if (Lifecycle.START_EVENT.equals(event.getType())) {
if (lifecycle instanceof Server) {
...
}
if( lifecycle instanceof Service ) {
...
}           
if (lifecycle instanceof StandardContext){
...
}
} else if (Lifecycle.AFTER_STOP_EVENT.equals(event.getType())) {
...
}
}
}
观察者可以通过事件来源(lifecycle)和事件类型(eventType)对事件分类处理。
四、 总结
tomcat中事件处理机制比较灵活,在日常工作的设计中值得借鉴,比如下面的业务场景:对客户投诉的创建、撤销、终止等,可以采用如下处理方式:
--生命周期管理--
1. 创建统一的投诉业务生命周期Lifecycle,如create、cancel、destroy等。
2. 定义投诉业务的状态枚举类(对应tomcat中LifecycleState),枚举类中定义每个状态对应的事件类型。
--观察者注册--
3. 创建观察者管理service(对应tomcat中的LifecycleSupport)。观察者列表可以通过spring bean方式注入。
--观察者通知--
4. 在生命周期中状态改变时,比如投诉创建时,发送事件通知,调用观察者管理service,通知观察者处理。
5. 包装观察者所需要的数据(对应tomcat中的LifecycleEvent),如事件来源、类型等,供观察者使用。
--观察者处理--
6. 定义实际观察者,按事件来源和类型分别做业务处理,比如投诉创建时,将投诉发生时用户的业务开通快照记录下来。
  转载至:http://learnworld.iteye.com/blog/1013751

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-332670-1-1.html 上篇帖子: tomcat 下运行php 下篇帖子: 基于Tomcat的WebSocket
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表