`
dicmo
  • 浏览: 66968 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Coder 爱翻译 How Tomcat Works 第五章 第一部分

    博客分类:
  • j2ee
阅读更多
Chapter 5: Container

一个容器是一个为servlet处理请求和给客户端填充response对象的模块。一个容器可以用
org.apache.catalina.Container接口表示。这里有四种类型的容器:Engine, Host, Context 和Wrapper。这章包含了Context和Wrapper。把其它两个容器放在后面第十三章讲解。

The Container Interface

一个容器必须实现了org.apache.catalina.Container。你看到了在第四章中,你传递一个Container实例给连接器的toContainer方法,这样连接器可以调用容器的invoke方法。回顾下面的Bootstrap类的代码:
HttpConnector connector = new HttpConnector(); 
SimpleContainer container = new SimpleContainer(); 
connector.setContainer(container);

第一件要注意的事情是在Catalina里面的容器在不同概念层次上的划分有下面四种类型的容器:

 Engine:
Represents the entire Catalina servlet engine. (代表整个Catalina的servlet engine)
 Host:
Represents a virtual host with a number of contexts.(代表一个有许多context的虚拟主机)
 Context:
Represents a web application. A context contains one or more wrappers.(代表一个web应用,一个context包含一个或更多wrapper)
 Wrapper:
Represents an individual servlet.(代表一个单独的servlet)

每个概念上的层次用org.apache.catalina包中的一个接口表示。这些接口是:Engine, Host, Context和 Wrapper。这四个接口都继承了Container接口。这四个容器的标准实现分别是:
StandardEngine, StandardHost, StandardContext和StandardWrapper。很具有代表性,他们都是org.apache.catalina.core包的一部分。

一个能完成应用功能的Catalina的部署不需要包含所有的这四种容器。例如:在这章的第一个应用程序的容器模块只包含了一个wrapper。第二个应用程序是一个拥有一个context和一个wrapper的容器模块。这章的应用程序中既没有host也没有engine。

一个容器可以有0个或更多低层次的的子容器。例如:一个context通常有一个或更多wrapper,一个host可以有0个或更多context。但是,一个wrapper是位于层次结构的最底层,他就不能包含子容器。增加一个子容器到一个容器中,你使用Container接口的addChild方法:
public void addChild(Container child);

从一个容器中移除一个子容器使用Container接口的removeChild方法:
public void removeChild(Container child);

此外,Container接口支持使用findChild和FindChildren方法找到一个容器的一个子容器和一个容器的所有子容器集合:
public Container findChild(String name); 
public Container[] findChildren();

一个容器也可以包含很多个像后面要讲到的支持组件:Loader, Logger, Manager, Realm和Resources.这里不得不提一下Container接口提供的get和set方法来把容器自己和组件联系起来的方法:getLoader 和setLoader, getLogger 和setLogger, getManager 和
setManager, getRealm 和setRealm,getResources 和 setResources。

更有趣的是,Container接口通过这种方式来指定:在部署的时候,一个Tomcat的管理员(administrator)通过修改配置文件(server.xml)决定一个容器是完成什么事情的。而这又是通过在一个容器中引入一个pipeline和一套valve来实现的。

注意:Tomcat 4 的Container接口和Tomcat 5的稍有一点不同。例如:Tomcat 4 接口有一个map方法,而在Tomcat 5中就没有。

Pipelining Tasks

一个pipeline包含了容器将要调用的任务(tasks)。一个valve代表一个具体的任务。一个容器的pipeline有一个(basic valve)基本的valve(阀),但是你还是可以添加任意多你想要添加的valve。valve的数量是由增加的valve的数量决定,但不包含basic valve。有趣的是,valve可以通过修改Tomcat的配置文件(server.xml)来动态地添加。

如果你了解servlet的filter,你就不难想象一个pipeline的valve是怎么工作的了。一个pipeline就像是一个filter chain,而每一个valve就是一个filter。就像filter一样,一个valve可以处理传递给它的request和response对象。当一个valve完成了处理工作,它就调用在pipeline中的下一个valve。而basic valve总是在最后被调用。

一个容器可以有一个pipeline。当一个容器的invoke方法被调用,容器传递处理任务到它的pipeline,这个pipeline就调用它的第一个valve,然后调用它后面的valve,依次调用到最后。
直到在pipeline中再也没有valve。你可以想象的到,你可以跟着下面的pipeline的invoke方法的伪代码:
// invoke each valve added to the pipeline
for (int n=0; n<valves.length; n++) { 
   valve[n].invoke( ... ); 
} 
// then, invoke the basic valve 
basicValve.invoke( ... );

但是,Tomcat的设计者选择了不同的方式,通过引入了org.apache.catalina.ValveContext接口。下面介绍它怎么工作的。

一个容器当它的invoke方法被连接器调用时,它打算做什么事情不能通过(hard code)硬编码实现。而是容器调用它的pipeline的invoke方法。Pipeline接口的invoke方法和Container接口的invoke方法相同:
public void invoke(Request request, Response response) 
   throws IOException, ServletException;

下面是Container接口的invoke方法在org.apache.catalina.core.ContainerBase类的实现
public void invoke(Request request, Response response) 
   throws IOException, ServletException { 
   pipeline.invoke(request, response); 
}

pipeline是容器内部的Pipeline接口的实例。

现在,pipeline必须确认所有的valve被添加,basic valve必须被调用一次。pipeline通过创建一个ValveContext接口的实例来完成valve的添加确认。ValveContext是作为一个pipeline的内部类实现的,所以ValveContext可以访问pipeline的所有成员。ValveContext接口的最重要的方法是invokeNext方法:
public void invokeNext(Request request, Response response) 
   throws IOException, ServletException

创建了一个ValveContext实例后,pipeline调用ValveContext的invokeNext方法。ValveContext将首先调用pipeline中的第一个valve,然后第一个valve在它完成了任务前将调用下一个valve。ValveContext把它自己传递给每一个valve,所以valve可以调用ValveContext的invokeNext方法。
public void invoke(Request request, Response response, 
   ValveContext ValveContext) throws IOException, ServletException

一个valve的invoke方法的实现:
public void invoke(Request request, Response response, 
   ValveContext valveContext) throws IOException, ServletException { 
   // Pass the request and response on to the next valve in our pipeline 
   valveContext.invokeNext(request, response); 
   // now perform what this valve is supposed to do 
     ... 
}

org.apache.catalina.core.StandardPipeline类是在所有容器的Pipeline的实现。在Tomcat 4中,这个类有一个叫做StandardPipelineValveContext的实现了ValveContext接口的内部类。
Listing 5.1: The StandardPipelineValveContext class in Tomcat 4   
 
protected class StandardPipelineValveContext implements ValveContext { 
   protected int stage = 0; 
   public String getInfo() { 
     return info; 
   } 
   public void invokeNext(Request request, Response response) 
     throws IOException, ServletException {  
     int subscript = stage; 
     stage = stage + 1;
    // Invoke the requested Valve for the current request thread 
     if (subscript < valves.length) { 
       valves[subscript].invoke(request, response, this); 
     } 
     else if ((subscript == valves.length) && (basic != null)) { 
       basic.invoke(request, response, this); 
     } 
     else { 
       throw new ServletException 
         (sm.getString("standardPipeline.noValve")); 
     } 
   } 
}

invokeNext方法使用下标(subscript)和状态(stage)来明确指出哪一个valve被调用过。当在pipeline的invoke方法第一个valve被调用时,下标值是0,状态值是1。因此,第一个valve(数组下标是0)被调用。在pipeline中的第一个valve接收ValveContext实例和调用它的invokeNext方法。这时,下标值是1,当然第二个valve被调用,以此类推。

当最后一个valve的invokeNext方法被调用时,下标值是等于valve的数量。最后,basic valve被调用。

Tomcat 5从StandardPipeline中移除了StandardPipelineValveContext类,而依靠org.apache.catalina.core.StandardValveContext。
Listing 5.2: The StandardValveContext class in Tomcat 5   
 
package org.apache.catalina.core; 
import java.io.IOException; 
import javax.servlet.ServletException; 
import org.apache.catalina.Request; 
import org.apache.catalina.Response; 
import org.apache.catalina.Valve; 
import org.apache.catalina.ValveContext; 
import org.apache.catalina.util.StringManager; 
 
public final class StandardValveContext implements ValveContext {
   protected static StringManager sm =  StringManager.getManager(Constants.Package); 
   protected String info =  "org.apache.catalina.core.StandardValveContext/1.0"; 
   protected int stage = 0; 
   protected Valve basic = null; 
   protected Valve valves[] = null; 
   public String getInfo() { 
     return info; 
 
   } 
 
public final void invokeNext(Request request, Response response) 
     throws IOException, ServletException {
  	 int subscript = stage; 
     stage = stage + 1; 
     // Invoke the requested Valve for the current request thread 
     if (subscript < valves.length) {        valves[subscript].invoke(request, response, this); 
     } 
     else if ((subscript == valves.length) && (basic != null)) {
  		basic.invoke(request, response, this); 
     } 
     else { 
       throw new ServletException 
         (sm.getString("standardPipeline.noValve")); 
     } 
   } 
 
   void set(Valve basic, Valve valves[]) { 
     stage = 0; 
     this.basic = basic; 
     this.valves = valves; 
   } 
}

你可以看见Tomcat 4中的StandardPipelineValveContext类和Tomcat 5 中的StandardValveContext类相似。

下面们将要详细讨论Pipeline, Valve和 ValveContext接口:
2
0
分享到:
评论
2 楼 dicmo 2010-12-10  
amwiacel 写道
一个容器可以用
org.apache.catalina.Container接口表示。这里有四种类型的容器:Engine, Host, Context 和Wrapper。 这种直译不是很好,其实这种分法是一种抽象模型,得从设计模式上去理解其意思。

谢谢指正。这个措词是不恰当。抽象层面的东西。
1 楼 amwiacel 2010-12-10  
一个容器可以用
org.apache.catalina.Container接口表示。这里有四种类型的容器:Engine, Host, Context 和Wrapper。 这种直译不是很好,其实这种分法是一种抽象模型,得从设计模式上去理解其意思。

相关推荐

    How tomcat works 中文版

    � jsp / servlet 开发人员,想了解 tomcat 内部机制的 coder ; � 想加入 tomcat 开发团队的 coder ; � web 开发人员,但对软件开发很有兴趣的 coder ; � 想要对 tomcat 进行定制的 coder 。 在阅读之前,希望...

    tomcat原理解析书(how-tomcat-works)中文版

    适合读者 1.jsp/servlet 开发人员,想了解 tomcat 内部机制的 coder; 2.想加入 tomcat 开发团队的 coder; 3.web 开发人员,但对软件开发很有兴趣的 coder; 4.想要对 tomcat 进行定制的 coder。

    Bad Programming Practices 101 Become a Better Coder by Learning How (Not) epub

    Bad Programming Practices 101 Become a Better Coder by Learning How (Not) to Program 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书

    The Clean Coder

    Martin, "The Clean Coder: A Code of Conduct for Professional Programmers" Prentice Hall | 2011 | ISBN: 0137081073 | 256 pages | PDF | 6 MB Programmers who endure and succeed amidst swirling ...

    phpcoder.rar

    phpcoder安装包。 直接下载安装即可。

    HDL-Coder详细教程

    HDL-Coder详细教程,有详细例子,源于官方例程,中文教程

    php coder编辑器

    PHPCoder用于快速开发和调试PHP应用程序,它很容易扩展和定制,完全能够符合开发者的个性要求.PHPCoder是一个非常实用的,功能强大的编程环境,而且它是免费的!

    MediaCoder答题器

    MediaCoder答题器

    simulink hdl coder 用户手册pdf

    HDL CODER 的用户手册,学习hdl coder参考用书,详细介绍了用simulink开发fpga的过程

    coder的建表语句

    coder的建表语句

    Embedded Coder.rar

    texasinstrumentsc2000.mlpkginstall 支持TI的C2000系列工具包,要求MATLAB R2017a及其以上版本。 安装方法:打开matlab,调整路径到mlpkginstall文件所在目录;在current folder窗口里双击mlpkginstall文件即可开始...

    mediacoder专业版

    mediacoder 5685专业版,无普通版的限制

    MediaCoder使用说明文档

    MediaCoder使用说明文档, mediaCoder usermanual,

    range coder.pdf

    range coder, algorithm, compressing.

    MediaCoder.5755专业破解版

    MediaCoder行业版一款针对VOD及KTV视频点播行业开发的,用于转换和处理带有多音轨内容的视频节目的软件。它具备业界领先的视频编码引擎,在高性能转码的同时保持高画质,并通过丰富的视频滤镜增强画面视觉效果。作为...

    matlab Embedded Coder Getting Started Guide.pdf

    Embedded Coder用于产生嵌入式处理器、目标快速原型板和大规模生产中使用的微处理器的可读的、紧凑的、快速的C和C++代码。Embedded Coder支持附加的MATLAB Coder™和Simulink Coder™配置选项,以及对生成代码的功能...

    MediaCoder64位专业破解版

    MediaCoder-Premium-x64 MediaCoder是最早开始使用GPU进行视频编码加速的影音转码软件之一。通过将原本完全依赖CPU的计算工作转移到GPU上进行,H.264和H.265编码所需的时间被大幅缩短。

    AI自动生成SQL语句的开源代码 sqlcoder-main.zip

    开源的AI自动生成SQL语句源代码,这款SQLCoder-70B-Alpha在文本到SQL的转换能力上超越了包括GPT-4在内的所有通用模型,它能更准确地理解你的需求,并生成相应的SQL查询。SQLCoder2和SQLCoder-7B模型已经向公众开放,...

    Mediacoder 使用帮助文档

    Mediacoder 入门使用说明+各种编码常用参数设置。

Global site tag (gtag.js) - Google Analytics