一、Container接口
tomcat中的servlet容器必须要实现org.apache.catalina.Container接口。tomcat中的容器包括:Engine、Host、Context、Wrapper。
有关这四个容器的类图如下:
常用方法:
addChild(Container child);
removeChild(Container child);
findChild(String name);
getLoader();
getLogger();
invoke();
...
在部署应用时,tomcat管理员可以通过编辑配置文件(server.xml)来决定是由哪种容器。
二、管道任务
管道中包含该servlet容器将要调用的任务。一个阀代表一个具体的执行任务。在servlet管道中,有一个基础阀,也可以添加任意数量的阀。
阀的数量 = 基础阀 + 额外添加的阀
当一个阀执行完成后,会调用下一个阀继续执行。基础阀总是最后一个执行(责任链模式)。
当调用一个容器的invoke()方法时,容器会将处理工作交给管道完成。而管道会调用其中的第1个阀开始处理。当第1个阀处理完成后,它会调用后续的阀继续执行任务,直到管道中的所有阀都处理完成。
但是,tomcat选择了另外一种实现方法,通过引入接口org.apache.catalina.ValveContext来实现阀的遍历执行。当连接器调用容器的invoke()方法后,容器会调用其管道的invoke方法。
现在管道必须保证添加到其中的所有阀及其基础阀都被调用一次,这个通过创建一个ValveContext接口实例来实现的。ValveContext是作为管道的一个内部类实现的,因此,ValveContext接口就可以访问管道中的所有成员。ValveContext接口中最重要的方法是invokeNext()。
在创建了ValveContext实例后,管道会调用ValveContext实例的invokeNext()方法。ValveContext实例会调用管道中的第1个阀,第1个阀执行完成后,会调用后面的阀继续执行。ValveContext实例会将自身传给每个阀,因此,每个阀都可以调用ValveContext实例的invokeNext方法了。
三、其他接口
3.1 Pipeline接口
常用方法:
getBasic();
setBasic();
addValve(Valve valve);
removeValve(Valve valve);
invoke(Request,Response);
3.2 Valve接口
阀是Valve接口的实例,用来处理接收到的请求。
常用方法:
getInfo();
invoke(Request request,Response response,ValveContext context);
3.3 ValveContext接口
常用方法:
getInfo();
invokeNext(Request request,Response response);
3.4 Contained接口
阀可以选择是否实现该接口。该接口的实现类可以通过接口中的方法至多与servlet容器相关联。
常用方法:
Container getContainer();
setContainer(Container container);
3.5 Wrapper接口
该接口是Wrapper容器的接口,Wrapper接口的实现类负责管理其基础servlet类的servlet生命周期,即,调用servlet的init()、service()、destroy()等方法。
常用方法:
load();//载入并初始化servlet类
allocate();//分配一个已经初始化的servlet实例
3.6 Context接口
Context接口的实例表示一个WEB应用程序,一个Context实例可以有一个或者多个Wrapper实例作为其子容器。
四、Wrapper应用程序
4.1 UML类图
4.2 UML序列图1
4.3UML序列图2
五、Context应用程序
上一个Wrapper应用程序只有一个servlet实例。当web应用程序需要多个servlet合作时,需要的servlet容器是Context。
该应用程序还需要使用一个映射器。本应用程序中的映射器是tomcat4中org.apache.catalina.Mapper接口的实现类。
Mapper接口中常用方法:
getContainer();
setContainer(Container container);
getProtocol();
setProtocol(String protocol);
...
5.1类图
Context容器是一个SimpleContext类的实例,SimpleContext类使用SimpleContextMapper类的实例作为其映射器,将SimpleContextValve作为基础阀。Context容器中额外添加了两个阀:SimpleIPLoggerValve和HeaderLoggerValve,并包含两个Wrapper实例作为其子容器,二者都是SimpleWrapper实例。这两个Wrapper实例使用SimpleWrapperValve作为其基础阀。
①当连接器接收到HTTP请求后,调用Context容器的invoke方法。
②管道中的invoke方法会调用所有添加到其容器中的阀,然后再调用其基础阀的invoke方法。
③在wrapper实例中,基础阀负责载入相关联的servlet类,并对请求进行相应。
④在包含子容器的Context实例中,基础阀使用映射器来查找一个子容器,该子容器负责处理接收到的请求。若找到了相应的子容器,则调用其invoke()方法,转向步骤①继续执行。
SimpleContext 与 SimplePipeline 明显是装饰设计模式