上一节,我们主要说的是Wrapper容器,这一节我们说Context容器。

再重申一遍,一个Context容器可以包含多个Wrapper容器;

一个Wrapper容器就表示一个独立的servlet。

Context应用程序

这里我们得提出一个新的组件----映射器,它帮助servlet容器---在这一节汇总就是Context实例选择一个子容器(这里就是Wrapper实例)来处理某个指定的请求。

首先咱们得明确几点;

映射器的作用就是联系一个父容器与他的若干个子容器,一个父容器可以有若干个映射器,为什么?因为有这样可以支持不同的协议。

例如一个映射器用来支持http协议,另一个映射器支持https协议(话说,http与https有什么区别,我就说一点,那个s代表security,安全,采取了另一种形式的保密措施,一般银行,证券交易所用https)

Mapper接口如下,我们这节使用的是其实现类,SimpleContextMapper类

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);
}

各个方法的名字都起的很好,大家应该可以见名知意。

下面是这一节的uml类图





通过说明的uml图,大家可以看到我们熟悉的SimpleContext"含有"一个SimpleContextMapper,现在我们看看代码

public class SimpleContext implements Context, Pipeline {

  public SimpleContext() {
    pipeline.setBasic(new SimpleContextValve());
  }

  protected HashMap<String, Container> children = new HashMap<String, Container>();
  protected Loader loader = null;
  protected SimplePipeline pipeline = new SimplePipeline(this);
  protected HashMap<String, String> servletMappings = new HashMap<String, String>();
  protected Mapper mapper = null;
  protected HashMap<String, Mapper> mappers = new HashMap<String, Mapper>();
  private Container parent = null;
  ......
}

现在我来说说这个几个属性;

mapper这是一个Mapper类型的是属性,如果一个容器只有一个映射器的话,那么就默认是它;如果一个容器有若干个映射器(以应对不同的网络协议例如http与https)那么mapper就置为空;

mappers这是hashmap类型的,里面放置容器的若干个映射器,以映射器支持的协议作为key;

servletMapping 也是hashmap,里面存放的是一个个映射路径与子容器的映射关系;例如如果访问uri为/servletA,就对应servletA这个servlet;

childen又是一个hashmap,里面存放了servletA这个名字对于的子容器(在这里就是Wrapper)

测试类如下;

public final class Bootstrap2 {

@SuppressWarnings("deprecation")
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();
    }
  }
}

我们先看看时序图

我直接从Context容器里的基础阀讲起,就是它SimpleContextValve(上一节的基础阀是SimpleWrapperValve)。基础阀之前的流程与上一节的内容一样,大家参照上一节。

public void invoke(Request request, Response response, ValveContext valveContext)
    throws IOException, ServletException {

   .....

    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);
  }

ok我们到SimpleContext的map方法里看看;

  public Container map(Request request, boolean update) {
    //this method is taken from the map method in org.apache.cataline.core.ContainerBase
    //the findMapper method always returns the default mapper, if any, regardless the
    //request's protocol
    Mapper mapper = findMapper(request.getRequest().getProtocol());
    if (mapper == null)
      return (null);

    // Use this Mapper to perform this mapping
    return (mapper.map(request, update));
  }

  public Mapper findMapper(String protocol) {
    // the default mapper will always be returned, if any,
    // regardless the value of protocol
    if (mapper != null)
      return (mapper);
    else
      synchronized (mappers) {
        return ((Mapper) mappers.get(protocol));
      }
  }

findMapper方法总是返回默认的那个映射器(前面我们已经说了,如果容器中只有一个映射器那它就是默认的,如果有多个,那么存储默认映射器的属性为空)如果有多个映射器就到mappers里去按照网络协议找;

  找到映射器之后,就简单了

  wrapper.invoke(request, response);

  这就回到上一节那部分了,调用Wrapper的所有阀,直到基础阀(在这一节里,wrapper的管道里只有基础阀,之前的两个阀,装到了context的管道里),进入wrapper后调用allocate.......

how tomcat works 5 servlet容器 下的更多相关文章

  1. how tomcat works 五 servlet容器 上

    servlet容器是用来处理请求servlet资源,并为Web客户端填充response对象的模块.在上一篇文章(也就是书的第四章)我们设计了SimpleContainer类,让他实现Containe ...

  2. Tomcat是一个Servlet容器?

    "Tomcat是一个Servlet容器",这句话对于2019年的程序员应该是耳熟能详的. 单纯的思考一下这句话,我们可以抽象出来这么一段代码: class Tomcat { Lis ...

  3. 19、配置嵌入式servlet容器(下)

    使用外置的Servlet   嵌入式Servlet容器:应用打成可执行的j ar 优点:简单.便携: 缺点:默认不支持JSP.优化定制比较复杂         使用定制器[ServerProperti ...

  4. httpServletRequest对象、filter、servlet、servlet容器、catalina、tomcat、以及web容器之间的关系

    学习servlet的时候经常感到疑惑 HttpServletRequest是服务器创建的?还是servlet容器创建的? 过滤器是服务器创建的?还是servlet容器创建的? serlet容器和tom ...

  5. Web服务器(Apache)与Servlet容器(Tomcat)

    之前一直比较迷惑Apache与Tomcat的关系,通过查询资料,有所了解,现记录于此. Apache与Tomcat 两者定位:Apache是HTTP Web服务器,Tomcat是Web容器. 有一个非 ...

  6. tomcat与jboss等容器的区别

    1.JBoss 是 J2EE 应用服务器,而 Tomcat 只是一个 Servlet 容器,或者说是一个简单的 J2EE 应用服务器. JBoss 中的 Servlet 容器还是 Tomcat. 与  ...

  7. Web容器、Servlet容器、Spring容器、SpringMVC容器之间的关系

    以下内容为个人理解,如有误还请留言指出,不胜感激! Web容器 web容器(web服务器)主要有:Apache.IIS.Tomcat.Jetty.JBoss.webLogic等,而Tomcat.Jet ...

  8. 为什么要有 Servlet ,什么是 Servlet 容器,什么是 Web 容器?

    本文已收录至 https://github.com/yessimida/yes ,这里有我的所有文章分类汇总,欢迎 star! 以下代码相信大家都很熟悉,大学时学 Java Web 都写过这样的代码. ...

  9. springboot(七) 配置嵌入式Servlet容器

    github代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-service ...

随机推荐

  1. 国内外主流BI工具介绍和点评

    商业智能的应用在国外已广为普及,并且开始不断探索大数据和云技术.而国内,商业智能BI工具在这几年才开始慢慢被接受,企业开始有意识地建立一体化数据分析平台,为经营决策提供分析. 从国内企业使用情况来看, ...

  2. windows 消除文件名中的快捷方式

    1)运行regedit进入注册表.2)依次打开:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer3)右侧框图,把 ...

  3. antlr 4新特性总结及与antlr v3的不同

    antlr 4新特性总结及与antlr v3的不同 学习曲线低.antlr v4相对于v3,v4更注重于用更接近于自然语言的方式去解析语言.比如运算符优先级,排在最前面的规则优先级最高: 层次更清晰. ...

  4. [sed]命令笔记

    sed是linux下经常用到的工具,英文全名为stream editor. sed 在windows上的实现可以在这里找到 http://gnuwin32.sourceforge.net/packag ...

  5. 全文检索Lucene (1)

    Lucene是apache开源的一个全文检索框架,很是出名.今天先来分享一个类似于HelloWorld级别的使用. 工作流程 依赖 我们要想使用Lucene,那就得先引用人家的jar包了.下面列举一下 ...

  6. hive元数据库表分析及操作

    在安装Hive时,需要在hive-site.xml文件中配置元数据相关信息.与传统关系型数据库不同的是,hive表中的数据都是保存的HDFS上,也就是说hive中的数据库.表.分区等都可以在HDFS找 ...

  7. 1089. Insert or Merge (25)

    题目如下: According to Wikipedia: Insertion sort iterates, consuming one input element each repetition, ...

  8. 3.QT中的debug相关的函数,以及文件锁的使用

     1  新建项目T33Debug main.cpp #include <QDebug> #include <QFile> #include <QMutex>   ...

  9. iOS中 为 iOS 建立 Travis CI 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博! 你是否曾经试着为 iOS 项目搭建一台支持持续集成的服务器,从我的个人经验而言,这可不是一个轻松的活.首先需要准备 ...

  10. SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP

    AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP之所以能得到广泛应用,主要是因为它将应用系统拆分分了2个部分 ...