Tomcat 系统架构与模式设计分析.docx
- 文档编号:10129542
- 上传时间:2023-05-23
- 格式:DOCX
- 页数:55
- 大小:756.65KB
Tomcat 系统架构与模式设计分析.docx
《Tomcat 系统架构与模式设计分析.docx》由会员分享,可在线阅读,更多相关《Tomcat 系统架构与模式设计分析.docx(55页珍藏版)》请在冰点文库上搜索。
Tomcat系统架构与模式设计分析
Tomcat总体结构
Tomcat的结构很复杂,但是Tomcat也非常的模块化,找到了Tomcat最核心的模块,您就抓住了Tomcat的“七寸”。
下面是Tomcat的总体结构图:
图1.Tomcat的总体结构
从上图中可以看出Tomcat的心脏是两个组件:
Connector和Container,关于这两个组件将在后面详细介绍。
Connector组件是可以被替换,这样可以提供给服务器设计者更多的选择,因为这个组件是如此重要,不仅跟服务器的设计的本身,而且和不同的应用场景也十分相关,所以一个Container可以选择对应多个Connector。
多个Connector和一个Container就形成了一个Service,Service的概念大家都很熟悉了,有了Service就可以对外提供服务了,但是Service还要一个生存的环境,必须要有人能够给她生命、掌握其生死大权,那就非Server莫属了。
所以整个Tomcat的生命周期由Server控制。
以Service作为“婚姻”
我们将Tomcat中Connector、Container作为一个整体比作一对情侣的话,Connector主要负责对外交流,可以比作为Boy,Container主要处理Connector接受的请求,主要是处理内部事务,可以比作为Girl。
那么这个Service就是连接这对男女的结婚证了。
是Service将它们连接在一起,共同组成一个家庭。
当然要组成一个家庭还要很多其它的元素。
说白了,Service只是在Connector和Container外面多包一层,把它们组装在一起,向外面提供服务,一个Service可以设置多个Connector,但是只能有一个Container容器。
这个Service接口的方法列表如下:
图2.Service接口
从Service接口中定义的方法中可以看出,它主要是为了关联Connector和Container,同时会初始化它下面的其它组件,注意接口中它并没有规定一定要控制它下面的组件的生命周期。
所有组件的生命周期在一个Lifecycle的接口中控制,这里用到了一个重要的设计模式,关于这个接口将在后面介绍。
Tomcat中Service接口的标准实现类是StandardService它不仅实现了Service借口同时还实现了Lifecycle接口,这样它就可以控制它下面的组件的生命周期了。
StandardService类结构图如下:
图3.StandardService的类结构图
从上图中可以看出除了Service接口的方法的实现以及控制组件生命周期的Lifecycle接口的实现,还有几个方法是用于在事件监听的方法的实现,不仅是这个Service组件,Tomcat中其它组件也同样有这几个方法,这也是一个典型的设计模式,将在后面介绍。
下面看一下StandardService中主要的几个方法实现的代码,下面是setContainer和addConnector方法的源码:
清单1.StandardService.SetContainer
viewplaincopytoclipboardprint?
01.publicvoidsetContainer(Containercontainer){
02.ContaineroldContainer=this.container;
03.if((oldContainer!
=null)&&(oldContainerinstanceofEngine))
04.((Engine)oldContainer).setService(null);
05.this.container=container;
06.if((this.container!
=null)&&(this.containerinstanceofEngine))
07.((Engine)this.container).setService(this);
08.if(started&&(this.container!
=null)&&(this.containerinstanceofLifecycle)){
09.try{
10.((Lifecycle)this.container).start();
11.}catch(LifecycleExceptione){
12.;
13.}
14.}
15.synchronized(connectors){
16.for(inti=0;i 17.connectors[i].setContainer(this.container); 18.} 19.if(started&&(oldContainer! =null)&&(oldContainerinstanceofLifecycle)){ 20.try{ 21.((Lifecycle)oldContainer).stop(); 22.}catch(LifecycleExceptione){ 23.; 24.} 25.} 26.support.firePropertyChange("container",oldContainer,this.container); 27.} publicvoidsetContainer(Containercontainer){ ContaineroldContainer=this.container; if((oldContainer! =null)&&(oldContainerinstanceofEngine)) ((Engine)oldContainer).setService(null); this.container=container; if((this.container! =null)&&(this.containerinstanceofEngine)) ((Engine)this.container).setService(this); if(started&&(this.container! =null)&&(this.containerinstanceofLifecycle)){ try{ ((Lifecycle)this.container).start(); }catch(LifecycleExceptione){ ; } } synchronized(connectors){ for(inti=0;i connectors[i].setContainer(this.container); } if(started&&(oldContainer! =null)&&(oldContainerinstanceofLifecycle)){ try{ ((Lifecycle)oldContainer).stop(); }catch(LifecycleExceptione){ ; } } support.firePropertyChange("container",oldContainer,this.container); } 这段代码很简单,其实就是先判断当前的这个Service有没有已经关联了Container,如果已经关联了,那么去掉这个关联关系——oldContainer.setService(null)。 如果这个oldContainer已经被启动了,结束它的生命周期。 然后再替换新的关联、再初始化并开始这个新的Container的生命周期。 最后将这个过程通知感兴趣的事件监听程序。 这里值得注意的地方就是,修改Container时要将新的Container关联到每个Connector,还好Container和Connector没有双向关联,不然这个关联关系将会很难维护。 清单2.StandardService.addConnector viewplaincopytoclipboardprint? 01.publicvoidaddConnector(Connectorconnector){ 02.synchronized(connectors){ 03.connector.setContainer(this.container); 04.connector.setService(this); 05.Connectorresults[]=newConnector[connectors.length+1]; 06.System.arraycopy(connectors,0,results,0,connectors.length); 07.results[connectors.length]=connector; 08.connectors=results; 09.if(initialized){ 10.try{ 11.connector.initialize(); 12.}catch(LifecycleExceptione){ 13.e.printStackTrace(System.err); 14.} 15.} 16.if(started&&(connectorinstanceofLifecycle)){ 17.try{ 18.((Lifecycle)connector).start(); 19.}catch(LifecycleExceptione){ 20.; 21.} 22.} 23.support.firePropertyChange("connector",null,connector); 24.} 25.} publicvoidaddConnector(Connectorconnector){ synchronized(connectors){ connector.setContainer(this.container); connector.setService(this); Connectorresults[]=newConnector[connectors.length+1]; System.arraycopy(connectors,0,results,0,connectors.length); results[connectors.length]=connector; connectors=results; if(initialized){ try{ connector.initialize(); }catch(LifecycleExceptione){ e.printStackTrace(System.err); } } if(started&&(connectorinstanceofLifecycle)){ try{ ((Lifecycle)connector).start(); }catch(LifecycleExceptione){ ; } } support.firePropertyChange("connector",null,connector); } } 上面是addConnector方法,这个方法也很简单,首先是设置关联关系,然后是初始化工作,开始新的生命周期。 这里值得一提的是,注意Connector用的是数组而不是List集合,这个从性能角度考虑可以理解,有趣的是这里用了数组但是并没有向我们平常那样,一开始就分配一个固定大小的数组,它这里的实现机制是: 重新创建一个当前大小的数组对象,然后将原来的数组对象copy到新的数组中,这种方式实现了类似的动态数组的功能,这种实现方式,值得我们以后拿来借鉴。 最新的Tomcat6中StandardService也基本没有变化,但是从Tomcat5开始Service、Server和容器类都继承了MBeanRegistration接口,Mbeans的管理更加合理。 以Server为“居” 前面说一对情侣因为Service而成为一对夫妻,有了能够组成一个家庭的基本条件,但是它们还要有个实体的家,这是它们在社会上生存之本,有了家它们就可以安心的为人民服务了,一起为社会创造财富。 Server要完成的任务很简单,就是要能够提供一个接口让其它程序能够访问到这个Service集合、同时要维护它所包含的所有Service的生命周期,包括如何初始化、如何结束服务、如何找到别人要访问的Service。 还有其它的一些次要的任务,如您住在这个地方要向当地政府去登记啊、可能还有要配合当地公安机关日常的安全检查什么的。 Server的类结构图如下: 图4.Server的类结构图 它的标准实现类StandardServer实现了上面这些方法,同时也实现了Lifecycle、MbeanRegistration两个接口的所有方法,下面主要看一下StandardServer重要的一个方法addService的实现: 清单3.StandardServer.addService viewplaincopytoclipboardprint? 01.publicvoidaddService(Serviceservice){ 02.service.setServer(this); 03.synchronized(services){ 04.Serviceresults[]=newService[services.length+1]; 05.System.arraycopy(services,0,results,0,services.length); 06.results[services.length]=service; 07.services=results; 08.if(initialized){ 09.try{ 10.service.initialize(); 11.}catch(LifecycleExceptione){ 12.e.printStackTrace(System.err); 13.} 14.} 15.if(started&&(serviceinstanceofLifecycle)){ 16.try{ 17.((Lifecycle)service).start(); 18.}catch(LifecycleExceptione){ 19.; 20.} 21.} 22.support.firePropertyChange("service",null,service); 23.} 24.} publicvoidaddService(Serviceservice){ service.setServer(this); synchronized(services){ Serviceresults[]=newService[services.length+1]; System.arraycopy(services,0,results,0,services.length); results[services.length]=service; services=results; if(initialized){ try{ service.initialize(); }catch(LifecycleExceptione){ e.printStackTrace(System.err); } } if(started&&(serviceinstanceofLifecycle)){ try{ ((Lifecycle)service).start(); }catch(LifecycleExceptione){ ; } } support.firePropertyChange("service",null,service); } } 从上面第一句就知道了Service和Server是相互关联的,Server也是和Service管理Connector一样管理它,也是将Service放在一个数组中,后面部分的代码也是管理这个新加进来的Service的生命周期。 Tomcat6中也是没有什么变化的。 组件的生命线“Lifecycle” 前面一直在说Service和Server管理它下面组件的生命周期,那它们是如何管理的呢? Tomcat中组件的生命周期是通过Lifecycle接口来控制的,组件只要继承这个接口并实现其中的方法就可以统一被拥有它的组件控制了,这样一层一层的直到一个最高级的组件就可以控制Tomcat中所有组件的生命周期,这个最高的组件就是Server,而控制Server的是Startup,也就是您启动和关闭Tomcat。 下面是Lifecycle接口的类结构图: 图5.Lifecycle类结构图 除了控制生命周期的Start和Stop方法外还有一个监听机制,在生命周期开始和结束的时候做一些额外的操作。 这个机制在其它的框架中也被使用,如在Spring中。 关于这个设计模式会在后面介绍。 Lifecycle接口的方法的实现都在其它组件中,就像前面中说的,组件的生命周期由包含它的父组件控制,所以它的Start方法自然就是调用它下面的组件的Start方法,Stop方法也是一样。 如在Server中Start方法就会调用Service组件的Start方法,Server的Start方法代码如下: 清单4.StandardServer.Start viewplaincopytoclipboardprint? 01.publicvoidstart()throwsLifecycleException{ 02.if(started){ 03.log.debug(sm.getString("standardServer.start.started")); 04.return; 05.} 06.lifecycle.fireLifecycleEvent(BEFORE_START_EVENT,null); 07.lifecycle.fireLifecycleEvent(START_EVENT,null); 08.started=true; 09.synchronized(services){ 10.for(inti=0;i 11.if(services[i]instanceofLifecycle) 12.((Lifecycle)services[i]).start(); 13.} 14.} 15.lifecycle.fireLifecycleEvent(AFTER_START_EVENT,null); 16.} publicvoidstart()throwsLifecycleException{ if(started){ log.debug(sm.getString("standardServer.start.started")); return; } lifecycle.fireLifecycleEvent(BEFORE_START_EVENT,null); lifecycle.fireLifecycleEvent(START_EVENT,null); started=true; synchronized(services){ for(inti=0;i if(services[i]instanceofLifecycle) ((Lifecycle)services[i]).start(); } } lifecycle.fireLifecycleEvent(AFTER_START_EVENT,null); } 监听的代码会包围Service组件的启动过程,就是简单的循环启动所有Service组件的Start方法,但是所有Service必须要实现Lifecycle接口,这样做会更加灵活。 Server的Stop方法代码如下: 清单5.StandardServer.Stop viewplaincopytoclipboardprint? 01.publicvoidstop()throwsLifecycleException{ 02.if(! started) 03.return; 04.lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT,null); 05.lifecycle.fireLifecycleEvent(STOP_EVENT,null); 06.started=false; 07.for(inti=0;i 08.if(services[i]instanceofLifecycle) 09.((Lifecycle)services[i]).stop(); 10.} 11.lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT,null); 12.} publicvoidstop()throwsLifecycleException{ if(! started) return; lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT,null); lifecycle.fireLifecycleE
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Tomcat 系统架构与模式设计分析 系统 架构 模式 设计 分析