Tomcat工作原理(五)-tomcat容器

来源:互联网 发布:java怎么调用构造函数 编辑:程序博客网 时间:2024/05/17 02:16

一个tomcat容器需要实现org.apache.catalina.Container,你可以在tomcat的连接器中使用setContainer方法传递一个容器给连接器。

Container接口

第一件需要注意的是在概念上tomcat有四种容器:

  • Engine 代表整个Catalina的servlet引擎。
  • Host 代表拥有若干个上下文的虚拟主机
  • Context 代表一个web应用,一个Context拥有若干个wrapper
  • Wrapper 代表一个单独的servlet

上述的每一个容器都在org.apache.catalina包中有对应的接口。这些接口都继承自Container,而StandardEngine, StandardHost, StandardContext, and StandardWrapper分别是他们的标准实现类
下图是他们的UML图:
这里写图片描述
一个“上层”容器可以拥有0个或者多个“下层容器”作为child,如一个Context可以拥有多个Wrapper ,但是Wrapper 作为作为最底层容器,不能拥有child。Container接口对于child进行了以下支持:
public void addChild(Container child);
public void removeChild(Container child);
public Container findChild(String name);
public Container[] findChildren();
一个容器也可以拥有其他的组件,比如Loader,Logger,Manager, Realm, and Resources这些将在以后的章节讨论。
更有趣的是 Container 接口被设计成 Tomcat 管理员可以通过server.xml 文件配置来决定其工作方式的模式它通过一个 pipeline(流水线)和一系列的阀门来实现,这些内容将会在下一节 Pipelining Task 中讨论。

Pipelining Tasks(流水线任务)

在这里主要要讨论的是其中的四个接口Pipeline(任务流), Valve(阀门), ValveContext, and Contained。
一个任务流包含了该容器要执行的所有任务。一个阀门表示一个特定的任务,在任务流中有一个最基本的阀门,同时你也可以根据需要任意添加阀门,阀门的数目定义为添加的阀门的个数(不包括基本阀门)。阀门可以通过编辑server.xml来自己添加。
如果你已经理解了servlet过滤器,那么任务流和它的阀门的工作方式不难想象。任务流就像过滤器链而阀门就像过滤器,跟过滤器一样,一个阀门可以操作传递给它的 request 和 response 方法。让一个阀门完成了处理,则进一步处理流水线中的下一个阀门,基本阀门总是在最后才被调用。
一个容器可以有一个流水线。当容器的 invoke 方法被调用的时候,容器将会处理流水线中的阀门,并一个接一个的处理,直到所有的阀门都被处理完毕。可以想象流水线的 invoke 方法的伪代码如下所示:

// 执行添加的阀门for (int n=0; n<valves.length; n++) {    valve[n].invoke( ... );}// 执行基本阀门basicValve.invoke( ... );

但是, Tomcat 的设计者选择了一种不同的通过org.apache.catalina.valves.ValveBase定义的方式来处理,在org.apache.catalina.valves包下,定义了各种不同的valves.他们继承自ValveBase,实现Valve中的invoke方法。在创建一个Valve对象之后,阀门调用getNext继续执行下一个方法。
现在来看看各接口的细节:

The Pipeline Interface 任务流接口

public  interface Pipeline{  public  Valve getBasic();  public  void setBasic(Valve paramValve);  public  void addValve(Valve paramValve);  public  Valve[] getValves();  public  void removeValve(Valve paramValve);  public  Valve getFirst();  public  boolean isAsyncSupported();  public  Container getContainer();  public  void setContainer(Container paramContainer);}

The Valve Interface 阀门接口

public  interface Valve{  public  Valve getNext();  public  void setNext(Valve paramValve);  public  void backgroundProcess();  public  void invoke(Request paramRequest, Response paramResponse)  throws IOException, ServletException;  public  boolean isAsyncSupported();}

The Contained Interface

一个阀门可以选择性的实现 org.apache.catalina.Contained 接口。该接口定义了其实现类跟一个容器相关联

public  interface Contained{  public  Container getContainer();  public  void setContainer(Container paramContainer);}

Wrapper接口

org.apache.catalina.Wrapper 接口表示了一个包装器。一个包装器是表示一个独立 servlet 定义的容器。包装器继承了 Container 接口,并且加了几个方法,包装器的实现类负责管理其下层 servlet 的生命周期,包括 servlet 的init,service,和 destroy 方法。由于包装器是最底层的容器,所以不可以将子容器添加给它。
包装器接口中重要方法有 allocate 和 load 方法。 allocate 方法负责定位该包装器表示的 servlet 的实例。 Allocate 方法必须考虑一个 servlet 是否实现了javax.servlet.SingleThreadModel 接口,该部分内容将会在 11 章中进行讨论。Load 方法负责 load 和初始化 servlet 的实例。

Context接口

一个 context 在容器中表示一个 web 应用。一个 context 通常含有一个或多个包装器作为其子容器。重要的方法包括addWrapper,createWrapper 等方法。

0 0
原创粉丝点击