Tomcat6源代码学习--容器层次结构和请求处理机制

来源:互联网 发布:php发布流程 编辑:程序博客网 时间:2024/05/23 12:12

    本文主要是从Tomcat6的源代码中推导出其核心容器的结构层次,和它们对请求的处理机制。
    Tomcat的核心容器是Engine、Host、Context、Wrapper。他们之间是一层套一层的父子关系,Engine拥有一个或者多个Host、Host拥有一个或多个Context、Context拥有多个Wrapper。同时它们4个又都是一个(is a)Container,具有一些共同的属性和行为。图一中的左半部分表达了这个结构:ContainerBase是一个实现了Container接口的抽象类,他封装了所有容器的默认实现。StandardEngine、StandardHost、StandardContext、StandardWrapper分别是对4个容器的具体实现,它们都继承自ContainerBase。StandardEngine的children成员就是Host、Host的children成员就是Context、由此类推。每个级别的容器都可以找到它们的子容器和父容器,当然Engine就没有父容器了,如果强行调用Engine的setParent(Container container)方法,就会得到一个又大又红的IllegalArgumentException,如果调用getParent()方法,则返回null。从这里也可以看出,Tomcat的设计师并没有完全按照里氏替换法则去设计,Engine并没有对parent的getter和setter行为,却还要继承ContainerBase。

    图一:Tomcat6各级容器的类图,图的内容经过简化,去掉了生命周期控制和logger、Cluster等扩张功能。(如果不能看到全图可以在我的相册中查看)

   
    以上便是4个容器的层次结构,请求最先到达Engine,当Engine处理了自己负责的工作后,把请求传递给他的下属容器Host,Host则在处理完后传递给Context,由此类推。那么它们之间是如何传递请求的呢?图一的右半部分对这个问题作了说明:每一个Container都拥有一个Pipeleine(管道),专门负责传递请求。父容器的Pipeline可以找到其子容器的Pipelien,由此将请求继续传递下去。请求在每个Pipeline中都会被适当的验证或处理(4个级别的容器各施其职)。这里因为会有各种各样的处理,所以将各种处理封装成一个个的Value(阀门),每种类型的Value专门负责做一项工作,比如验证Request的有效性、写日志。也就是说,每个Pipeline里面有多个Value,请求先到达第一个Value,Value对其做一些工作,当工作做完后,将请求传递到给下一个Value。每个Pipeline的最后都会有个一BasicValue,它负责把寻找下一级容器的Pipeline,将请求传递过去,比如Engine的StandardEngineValue、Host的StanadrdHostValue。图二画出了Tomcat6中的所有类型的Value,它们分别被各个Pipeline使用。
   
    这里有几点需要说明:
    1 对4个级别容器的层次结构,Tomcat使用了组合模式(Composite),这有利于在各个级别的容器间游走,同时复用了共同的东西。而这个设计的难度因该就在于对其抽象基类粒度的把握,究竟什么东西应该放在基类中,那些不应该?如前面提到的parent属性,虽然Host、Context、Wrapper都用到了,但Engine却不需要这个属性。
    2 对请求的处理过程,Tomcat使用了职责链模式(Chain of Responsility),这里的优点很明确,将可能产生变动的各种处理动作单独提炼出来,封装成各种Value,而Pipeline则像是一个可以插入各种Value的插槽,当Value有变动的时候,我们只需要调整Value在Pipeline中的位置即可(在Tomcat启动时组装),对整个流程框架不会产生影响。缺点也比较明显,就是每处理一个请求,都要经过4个Pipeline和很多的Value,效率会有所降低。
    3 各个Container和它们的Pipeline、Value的组装发生在Tomcat启动的时候,而不是动态组装的。Tomcat启动的时候主要做了两件事情:通过配置文件组装各个组建、启动容器。
    4  当请求传递给Engine的时候,其实就是Request和Response对象,这个时候Response基本是空的,需要在后继的处理中完善它的内容。当这两个对象在各个容器中传递的时候,各个容器根据自己的职责对其中的Request进行验证,同时不断完善Response的内容,最后将它们返回给客户端。
    5  菜鸟一个,如有错误,请指出 Orz

    图二:Tomcat6完整的Value

原创粉丝点击