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.SetContainerviewplaincopytoclipboardprint?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;iconnectors.length;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;iconnectors.length;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.addConnectorviewplaincopytoclipboardprint?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。还有其它的一些次要的任务,