`
dicmo
  • 浏览: 68525 次
  • 性别: 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。 这种直译不是很好,其实这种分法是一种抽象模型,得从设计模式上去理解其意思。

相关推荐

    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删除 查看此书详细信息请在美国亚马逊官网搜索此书

    phpcoder.rar

    PHPCoder是一款专为PHP开发者设计的高效代码编辑器,旨在提供一个轻量级且功能丰富的开发平台。这款软件以其便捷性、易用性和强大的功能深受程序员喜爱。在本篇文章中,我们将深入探讨PHPCoder的各项特性、安装过程...

    MediaCoder答题器

    6. 插件扩展:MediaCoder有一个开放的插件架构,用户可以通过安装第三方插件来增加新的编码解码器、滤镜和其他功能,扩展其应用范围。 7. 用户友好:MediaCoder的界面简洁直观,即便是对编码不熟悉的用户也能快速...

    mediacoder专业版

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

    simulink hdl coder 用户手册pdf

    综上所述,Simulink HDL Coder 作为一款先进的工具,极大地简化了从算法设计到 FPGA 实现的整个过程,是现代电子设计自动化领域不可或缺的一部分。通过掌握其使用方法和技术要点,工程师们能够更高效地完成复杂的 ...

    Mediacoder基础教程

    Mediacoder是一款强大的多媒体编码工具,专为音频和视频转换而设计,支持多种格式,如MP4、AVI、MKV等。本教程将深入讲解如何利用Mediacoder进行视频压制,优化视频质量,同时合理权衡码率与视频大小的关系。 **1. ...

    matlab Embedded Coder Getting Started Guide.pdf

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

    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 ...

    CoolCoder 类生成工具

    虽然CoolCoder能够自动化大部分工作,但开发者依然可以自定义模板,对生成的代码进行微调,以满足特定项目的需求。这种灵活性确保了生成的代码既高效又符合项目风格。 6. **提高开发效率**: 使用CoolCoder,...

    MediaCoder

    MediaCoder是一款功能强大的多媒体转换工具,它支持广泛的音频和视频编码格式,使用户能够轻松地在不同设备之间转换媒体文件。这款软件适用于个人用户、专业音频和视频制作人员,以及那些希望在各种设备上享受多媒体...

    php coder编辑器

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

    matlab coder基本函数教程

    ### MATLAB Coder 基本函数教程 #### MATLAB Coder 概述 MATLAB Coder 是一款能够将 MATLAB 代码转换成独立的 C 或 C++ 代码的强大工具。这一过程对于那些希望在非 MATLAB 环境下部署 MATLAB 代码的应用开发者来说...

    HDL-Coder详细教程

    ### HDL-Coder详细教程知识点概述 #### 一、生成HDL代码前的准备工作 在开始从Simulink模型生成HDL代码之前,需要完成一系列的准备工作,确保模型能够顺利生成高质量的代码。 ##### 1.1 使用`hdlsetup`进行模型...

    MediaCoder.5755专业破解版

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

    MediaCoder使用说明文档

    MediaCoder使用说明文档, mediaCoder usermanual,

    MatlabCoder使用-Matlab Coder的基本使用.pdf

    Matlab Coder是Mathworks公司推出的一款用于将Matlab代码转换成高效C代码的工具。从2004年开始,Matlab陆续在Simulink中添加了Embeded Matlab Function模块,2007年在Real-Time Workshop中引入了emlc函数(现在的...

    Embedded Coder.rar

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

    magicalcoder文件去域名

    接下来,我们讨论"magicalcoder文件去域名"的第二个方面——软件授权限制的解除。通常,商业软件会设定一定的授权机制,包括使用期限、设备数量或特定的使用环境(如特定域名)。这些限制是为了保护知识产权,防止...

Global site tag (gtag.js) - Google Analytics