您的位置:首页 > 运维架构 > Tomcat

Tomcat原理学习---容器Container

2014-06-12 22:35 507 查看
容器是一个处理用户servlet请求并返回对象给web用户的模块。
有四种容器:Engine(引擎), Host(主机), Context(上下文), 和 Wrapper(包装器)。
Container接口被设计成Tomcat管理员可以通过server.xml文件配置来决定其工作方式的模式。它通过一个pipeline(流水线)和一系列的阀门来实现。
org.apache.catalina中四个相关的接口:Pipeline, Valve, ValveContext, 和Contained。 

Pipelining Tasks(流水线任务) :

一个pipeline包含了该容器要唤醒的所有任务。每一个阀门表示了一个特定的任务。流水线必须保证说要添加给它的阀门必须被调用一次,流水线通过创建一个ValveContext接口的实例来实现它。ValveContext是流水线的的内部类,这样ValveContext就可以访问流水线中所有的成员。在创建一个ValveContext实例之后,流水线调用ValveContext的invokeNext方法。ValveContext会先唤醒流水线的第一个阀门,然后第一个阀门会在完成它的任务之前唤醒下一个阀门。ValveContext将它自己传递给每一个阀门,那么该阀门就可以调用ValveContext的invokeNext方法。

The Pipeline Interface流水线接口:
我们提到的流水线的第一个方法是它的Pipeline接口的invoke方法,该方法会开始唤醒流水线的阀门。流水线接口允许你添加一个新的阀门或者删除一个阀门。最后,可以使用setBasic方法来分配一个基本阀门给流水线,getBasic方法会得到基本阀门。最后被唤醒的基本阀门,负责处理request和回复response。

The Value Interface阀门接口:
阀门接口表示一个阀门,该组件负责处理请求。该接口有两个方法,invoke和getInfo方法。Invoke方法如上所述,getInfo方法返回阀门的信息。

The ValveContext Interface 阀门上下文接口 :
阀门上下文接口有两个方法,invokeNext方法如上所述,getInfo方法会返回阀门上下文的信息。

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

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

The Context Interface 上下文(Context)接口 :
一个context在容器中表示一个web应用。一个context通常含有一个或多个包装器作为其子容器。 重要的方法包括addWrapper, createWrapper 等方法。

The Wrapper Application(包装器应用程序) :
这个应用程序展示了如何写一个简单的容器模型。该应用程序的核心类是ex05.pyrmont.core.SimpleWrapper,它实现了Wrapper接口。SimpleWrapper类包括一个Pipeline(由ex05.pyrmont.core.SimplePipeline实现)和一个Loader类(ex05.pyrmont.core.SimpeLoader)来加载一个servlet。流水线包括一个基本阀门(ex05.pyrmont.core.SimpleWrapperValve)和两个另外的阀门(ex05.pyrmont.core.ClientIPLoggerValve
和 ex05.pyrmont.core.HeaderLoggerValve)

ex05.pyrmont.core.SimpleLoader:
容器中加载servlet的任务被分配给了Loader实现。在该程序中SimpleLoader就是一个Loader实现。它知道如何定位一个servlet,并且通过getClassLoader获得一个java.lang.ClassLoader实例用来查找servlet类位置。 SimpleLoader定义了3个变量,第一个是WEB_ROOT用来指明在哪里查找servlet类。 

ex05.pyrmont.core.SimplePipeline:
SimplePipeline实现了org.apache.catalina.Pipeline接口。该类中最重要的方法是invoke方法,其中包括了一个内部类SimplePipelineValveContext。SimplePipelineValveContext实现了org.apache.catalina.ValveContext接口

ex05.pyrmont.core.SimpleWrapper:
该类实现了org.apache.catalina.Wrapper接口并且实现了allocate方法和load方法,该类声明了如下变量: 
private Loader loader; 
protected Container parent = null; 
loader变量用于加载一个servlet类。Parent变量表示该包装器的父容器。这意味着,该容器可以是其它容器的子容器,例如Context。

    getLoader方法用于返回一个Loader对象用于加载一个servlet类。如果一个包装器跟一个加载器相关联,会返回该加载器。否则返回其父容器的加载器,如果没有父容器,则返回null。 

    SimpleWrapper类有一个流水线和该流水线的基本阀门。这些工作在SimpleWrapper的构造函数中完成。 

   

    ex05.pyrmont.core.SimpleWrapperValve:

    SimpleWrapperValve类是一个给SimpleWrapper类专门处理请求的基本阀门。

    由于SimpleWrapperValve被当做一个基本阀门来使用,它的invoke方法不需要invokeNext方法。 Invoke方法调用SimpleWrapper的allocate方法获得servlet的一个实例。然后调用servlet 的service方法。注意包装器流水线的基本阀门唤醒的是servlet的service方法,而不是wrapper方法自己的。 

    ex05.pyrmont.valves.ClientIPLoggerValve:

    ClientIPLoggerValve是一个阀门,它打印出客户端的IP地址到控制台。

    ex05.pyrmont.valves.HeaderLoggerValve:

    该类跟ClientIPLoggerValve类非常相似。HeaderLoggerValve是一个阀门打印请求头部到控制台上。

    ex05.pyrmont.startup.Bootstrap1:

    创建HttpConnector 和SimpleWrapper类的实例以后,主方法里分配ModernServlet给SimpleWrapper 的setServletClass方法,告诉包装器要加载的类的名字以便于加载。

    然后它创建了加载器和两个阀门然后将把加载器给包装器。

    然后把两个阀门添加到包装器流水线中。  

    最后,把包装器当做容器添加到连接器中,然后初始化并启动连接器。

    The Context Application:

    若需要多个包装器来包装多
4000
个servlet时,tomcat4需要一个map来处理这些子容器。(tomcat5使用另一种机制来查找子容器)

    在这个程序中,mapper是ex05.pyrmont.core.SimpleContextMapper类的一个实例,它继承了Tomcat  4中的org.apache.catalina.Mapper接口。

     public Container getContainer(); 
 public void setContainer(Container container); 
 public String getProtocol(); 
 public void setProtocol(String protocol); 
 public Container map(Request request, boolean update); 
getContainer返回该容器的mapper,
setContainer方法用于联系一个容器到mapper。 
getProtocol返回该mapper负责处理的协议, 
setProtocol用于分配该容器要处理的协议。map方法返回处理一个特殊请求的子容器。 

1.    一个容器有一个流水线,容器的invoke方法会调用流水线的invoke方法。 
2.    流水线的invoke方法会调用添加到容器中的阀门的invoke 方法,然后调用基本阀门的invoke方法。 
3.    在一个包装器中,基本阀门负责加载相关的servlet类并对请求作出相应。 
4.    在一个有子容器的上下文中,基本法门使用mapper来查找负责处理请求的子容器。如果一个子容器被找到,子容器的invoke方法会被调用,然后返回步骤1。 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: