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

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

    博客分类:
  • j2ee
阅读更多
The Context Application

这章的第一个应用,你了解了怎么部署一个只有一个wrapper组成的简单的web应用程序。这个应用中只有一个servlet。在一个应用中,只要一个单独的servlet是可能的,但大多数情况下需要更多。在这种情况下,你需要和wrapper相比不同的容器类型。你就需要一个context。

第二个应用程序演示了怎么使用一个有两个wrapper的context,context包装了两个servlet类。当有多于一个wrapper的时候,你就需要用到一个映射器(mapper)。mapper它是一个帮助容器(本例中是context)选择一个子容器来处理特定的请求的组件。

注意一个mapper只能在Tomcat 4中找到,在Tomcat 5中使用另外一种方式找到一个子容器。

mapper是ex05.pyrmont.core.SimpleContextMapper类的实例,它实现org.apache.catalina.Mapper接口。
一个容器也使用多个mapper来支持多协议。这种情况下,一个mapper支持一种请求协议。例如:一个容器可能有一个为HTTP协议的mapper,另外一个是HTTPS协议的mapper。
Listing 5.13: The Mapper interface   
 
package org.apache.catalina; 
public interface 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和一个容器相关联。getProtocal方法返回这个mapper负责处理的协议,setProtocol方法用来指配这个mapper负责处理的协议的名字。map方法返回一个用来处理特定的请求的子容器。
类图:


SimpleContext类代表一个context。它使用SimpleContextMapper作为它的mapper,SimpleContextValve作为basic valve。两个valve:ClientIPLoggerValve 和HeaderLoggerValve
被添加到context。两个wrapper,用SimpleWrapper代表,被作为子容器添加到context。
wrapper使用SimpleWrapperValve作为它们的basic valve,但是没有其他的valve。

Context应用程序使用相同的loader和两个valve。但是loader和valve是和context相关联的,而不是和wrapper相关联。这样,loader可以被所有的wrapper使用。context被指配为一个连接器的容器。此外,连接器在收到一个HTTP请求时将调用context的invoke方法。

 1:一个容器有一个pipeline。容器的invoke方法调用pipeline的invoke方法。
 2:pipeline的invoke方法调用所有的添加在容器里的valve。然后调用它的basic valve的invoke方法。
 3:在一个wrapper中,basic valve负责加载相关联的servlet和相关request。
 4:在一个有子容器的context中,basic valve使用mapper来找到一个负责处理请求的子容器。如果一个子容器被找到,它调用子容器的invoke方法,然后返回第一步。

现在看看在实现中的处理:
SimpleContext类的invoke方法调用pipeline的invoke方法:
The SimpleContext class's invoke method calls the pipeline's invoke method. 
   public void invoke(Request request, Response response) 
     throws IOException, ServletException { 
     pipeline.invoke(request, response); 
   }

pipeline是由SimplePipeline类代表。它的invoke方法:
public void invoke(Request request, Response response) 
     throws IOException, ServletException { 
     // Invoke the first Valve in this pipeline for this request 
     (new SimplePipelineValveContext()).invokeNext(request, response); 
   }

SimpleContextValve使用context的mapper找到wrapper:
// Select the Wrapper to be used for this Request 
Wrapper wrapper = null; 
  try { 
    wrapper = (Wrapper) context.map(request, true); 
  }

如果找到一个wrapper,它的invoke方法将被调用。
wrapper.invoke(request, response);

一个应用程序中的wrapper是SimpleWrapper类代表的。这里invoke方法:
public void invoke(Request request, Response response) 
    throws IOException, ServletException { 
    pipeline.invoke(request, response); 
  }

这个pipeline是一个SimplePipeline的实例。这个wrapper除了basic valve(SimpleArapperValve的实例)就没有其他valve。wrapper的pipeline调用SimpleWrapperValve类的invoke方法来分配servlet,调用它的service方法。

注意wrapper和一个loader是不相关联的,但是和context是相关联的。SimpleWrapper类的getLoader方法返回父类的loader。

SimpleContext, SimpleContextValve, SimpleContextMapper和Bootstrap2

ex05.pyrmont.core.SimpleContextValve

这个类代表SimpleContext的basic valve。它的重要方法:invoke:
public void invoke(Request request, Response response,ValveContext valveContext) 
   throws IOException, ServletException { 
   // Validate the request and response object types 
   if (!(request.getRequest() instanceof HttpServletRequest) || 
     !(response.getResponse() instanceof HttpServletResponse)) { 
     return; 
   }
   // Disallow any direct access to resources under WEB-INF or META-INF 
   HttpServletRequest hreq = (HttpServletRequest) request.getRequest(); 
   String contextPath = hreq.getContextPath(); 
   String requestURI = ((HttpRequest) request).getDecodedRequestURI(); 
   String relativeURI = requestURI.substring(contextPath.length()).toUpperCase();
   Context context = (Context) getContainer(); 
   // Select the Wrapper to be used for this Request 
   Wrapper wrapper = null; 
   try { 
     wrapper = (Wrapper) context.map(request, true); 
   }catch (IllegalArgumentException e) { 
     badRequest(requestURI, (HttpServletResponse) 
       response.getResponse()); 
       return; 
   }
   if (wrapper == null) { 
     notFound(requestURI, (HttpServletResponse) response.getResponse()); 
     return; 
   } 
   // Ask this Wrapper to process this Request 
   response.setContext(context); 
   wrapper.invoke(request, response); 
} 


ex05.pyrmont.core.SimpleContextMapper

SimpleContextMapper类,实现了org.apache.catalina.Mapper接口。
Listing 5.15: The SimpleContextMapper class   
 
package ex05.pyrmont.core; 
 
import javax.servlet.http.HttpServletRequest; 
import org.apache.catalina.Container; 
import org.apache.catalina.HttpRequest; 
import org.apache.catalina.Mapper; 
import org.apache.catalina.Request; 
import org.apache.catalina.Wrapper; 
 
public class SimpleContextMapper implements Mapper { 
 
   private SimpleContext context = null; 
   public Container getContainer() { 
     return (context); 
   }
  public void setContainer(Container container) { 
     if (!(container instanceof SimpleContext)) 
       throw new IllegalArgumentException ("Illegal type of container"); 
       context = (SimpleContext) container; 
   } 
  public String getProtocol() { 
     return null; 
   } 
   public void setProtocol(String protocol) {  }
   public Container map(Request request, boolean update) { 
     // Identify the context-relative URI to be mapped 
     String contextPath = ((HttpServletRequest) request.getRequest()).getContextPath(); 
     String requestURI = ((HttpRequest) request).getDecodedRequestURI(); 
     String relativeURI = requestURI.substring(contextPath.length()); 
     // Apply the standard request URI mapping rules from 
     // the specification 
     Wrapper wrapper = null; 
     String servletPath = relativeURI; 
     String pathInfo = null; 
     String name = context.findServletMapping(relativeURI); 
     if (name != null) 
       wrapper = (Wrapper) context.findChild(name);
  	   return (wrapper);
}
}

SetContainer方法当在你如果传递的一个容器不是SimpleContext的实例,它将抛出一个IllegalArgumentException异常。map方法返回一个子容器(wrapper)负责来处理请求。map方法有两个参数,一个request对象和一个boolean值。实现将忽略第二个参数。这个方法是从请求对象中获取context路径和使用context的findServletMapping方法获取相关的路径名。如果一个路径名被找到,它使用context的findChild方法获取一个Wrapper的实例。

ex05.pyrmont.core.SimpleContext

SimpleContext类是context的实现。它是与连接器相关联的主容器。但是处理每一个单独的servlet是wraper完成的。这个应用有两个servlet:PrimitiveServlet 和ModernServlet。每一个wrapper有一个名字。PrimitiveServlet 的wrapper名字是Primitive,ModernServlet的wrapper的名字是Morden。SimpleContext决定哪一个wrapper将被调用来处理每一个请求。你必须映射请求URL和wrapper的名字。这个应用中,我们有两个URL可以用来调用两个wrapper。第一个是/Primitive,是用来映射到wrapper Primitive。第二个是/Modern,是映射到wrapper Modern。

这里有很多Container和Context接口的方法在SimpleContext中必须实现。大多方法是空方法。

addServletMapping:增加一个URL/wrapper名字对。你每增加一个URL就可以用给出的相应的名字来调用这个wrapper。
findServletMapping:获取给出的URL对应的wrapper的名字。这个方法用来找到哪个wrapper应该被某个特定的URL调用。如果给出的URL没有使用addServletMapping方法来注册,这个方法就返回null。
addMapper:给context增加一个mapper。SimpleContext类声明了mapper变量和mappers变量。mapper是指默认mapper,而mappers包含所有SimpleContext实例的mapper。第一个增加到context的mapper就是默认的mapper。
findMapper:找到正确的mapper。在SimpleContext,它返回默认mapper。
Map:返回负责处理这个请求的wrapper。

此外,SimpleContext也提供addChild、findChild和findChildren方法的实现。addChild方法用来把一个wrapper添加到context中,findChild方法通过名字来找到一个wrapper,findChildren方法返回SimpleContext中的所有wrapper实例。

ex05.pyrmont.startup.Bootstrap2
Listing 5.16: The Bootstrap2 class   
 
package ex05.pyrmont.startup; 
import ex05.pyrmont.core.SimpleContext; 
import ex05.pyrmont.core.SimpleContextMapper; 
import ex05.pyrmont.core.SimpleLoader; 
import ex05.pyrmont.core.SimpleWrapper; 
import ex05.pyrmont.valves.ClientIPLoggerValve; 
import exO5.pyrmont.valves.HeaderLoggerValve; 
import org.apache.catalina.Connector; 
import org.apache.catalina.Context; 
import org.apache.catalina.Loader; 
import org.apache.catalina.Mapper; 
import org.apache.catalina.Pipeline; 
import org.apache.catalina.Valve; 
import org.apache.catalina Wrapper; 
import org.apache.catalina.connector.http.HttpConnector; 
 
public final class Bootstrap2 { 
   public static void main(String[] args) { 
    HttpConnector connector = new HttpConnector(); 
    Wrapper wrapper1 = new SimpleWrapper(); 
    Wrapper1.setName("Primitive"); 
    wrapper1.setServletClass("PrimitiveServlet"); 
    Wrapper wrapper2 = new SimpleWrapper(); 
    wrapper2.setName("Modern"); 
    wrapper2.setServletClass("ModernServlet");
    Context context = new SimpleContext(); 
    context.addChild(wrapper1); 
    context.addChild(wrapper2);
    Valve valve1 = new HeaderLoggerValve(); 
    Valve valve2 = new ClientIPLoggerValve(); 
    ((Pipeline) context).addValve(valve1); 
    ((Pipeline) context).addValve(valve2); 
    Mapper mapper = new SimpleContextMapper(); 
    mapper.setProtocol("http"); 
    context.addMapper(mapper); 
    Loader loader = new SimpleLoader(); 
    context.setLoader(loader); 
    // context.addServletMapping(pattern, name); 
    context.addServletMapping("/Primitive", "Primitive"); 
    context.addServletMapping("/Modern", "Modern"); 
    connector.setContainer(context);
    try { 
       connector.initialize(); 
       connector.start(); 
       // make the application wait until we press a key. 
       System.in.read(); 
     } catch (Exception e) { 
       e.printStackTrace(); 
     } 
   } 
} 

主方法开始实例化Tomcat默认连接器和两个wrapper:wrapper1和wrapper2。
HttpConnector connector = new HttpConnector(); 
Wrapper wrapper1 = new SimpleWrapper(); 
wrapper1.setName("Primitive");  
wrapper1.setServletClass("PrimitiveServlet"); 
    
Wrapper wrapper2 = new SimpleWrapper(); 
wrapper2.setName("Modern"); 
wrapper2.setServletClass("ModernServlet");

然后,主方法创建一个SimpleContext的实例,添加wrapper1和wrapper2作为SimpleContext的容器的子容器,实例化两个valveClientIPLoggerValve和 HeaderLoggerValve,
并把他们两个valve添加到SimpleContext。
Context context = new SimpleContext(); 
context.addChild(wrapper1); 
context.addChild(wrapper2); 
 
Valve valve1 = new HeaderLoggerValve(); 
Valve valve2 = new ClientIPLoggerValve(); 
 
((Pipeline) context).addValve(valve1); 
((Pipeline) context).addValve(valve2);

接下来它构建一个mapper对象,并把mapper添加到SimpleContext。mapper负责找到在context里的子容器,让其来处理HTTP请求。
Mapper mapper = new SimpleContextMapper(); 
mapper.setProtocol("http"); 
context.addMapper(mapper);

加载servlet类,你需要一个loader。这里你使用SimpleLoader类,就像第一个应用程序一样。但是,不同时是增加两个wrapper,loader被添加到context里。wrapper将使用getLoader方法找到loader,因为context是他们的父容器。
Loader loader = new SimpleLoader(); 
context.setLoader(loader);

现在,该添加servlet映射了。为你添加的两个wrapper作映射。
    // context.addServletMapping(pattern, name); 
    context.addServletMapping("/Primitive", "Primitive"); 
    context.addServletMapping("/Modern", "Modern");

最后,把context作为容器指配给连接器,初始化并启动连接器。
connector.setContainer(context); 
    try { 
      connector.initialize(); 
      connector.start();

                                                      第五章 完
  • 大小: 67.5 KB
2
0
分享到:
评论

相关推荐

    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安装包。 直接下载安装即可。

    matlab Embedded Coder Getting Started Guide.pdf

    Embedded Coder用于产生嵌入式处理器、目标快速原型板和大规模生产中使用的微处理器的可读的、紧凑的、快速的C和C++代码。...你可以将第三方开发环境引入到工程构建过程中,以产生用于在嵌入式系统上应用的可执行文件。

    HDL-Coder详细教程

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

    php coder编辑器

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

    simulink hdl coder 用户手册pdf

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

    MediaCoder答题器

    MediaCoder答题器

    coder的建表语句

    coder的建表语句

    Embedded Coder.rar

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

    mediacoder专业版

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

    MediaCoder使用说明文档

    MediaCoder使用说明文档, mediaCoder usermanual,

    一维码第三方CODER

    一维码第三方CODER

    range coder.pdf

    range coder, algorithm, compressing.

    MediaCoder.5755专业破解版

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

    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模型已经向公众开放,...

Global site tag (gtag.js) - Google Analytics