博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
how tomcat works 总结 二
阅读量:6500 次
发布时间:2019-06-24

本文共 5568 字,大约阅读时间需要 18 分钟。

第五章 servlet容器

第 5 章讨论 container 模块。container 指的是 org.apache.catalina.Container 接口,有4 种类型的 container:engine, host, context 和 wrapper。这章提供了两个工作于 context 和wrapper 的程序。
容器共分四类,类图例如以下:
一个wrapper就是一个servlet;
一个context包括若干个wrapper;
本章分了两个部分,第一部分是wrapper,第二部分是context。

第一部分 wrapper

这一章说白了就是具体分解了第四章SimpleContainer中的invoke方法!
public class SimpleWrapper implements Wrapper, Pipeline {  // the servlet instance  private Servlet instance = null;  private String servletClass;  private Loader loader;  private String name;  private SimplePipeline pipeline = new SimplePipeline(this);  protected Container parent = null;    public SimpleWrapper() {    pipeline.setBasic(new SimpleWrapperValve());  }  public synchronized void addValve(Valve valve) {    pipeline.addValve(valve);  }  ...}
既然说到了容器,就得说说管道(每一级容器中,都有一个管道);把我们的命令比作流水,在(流水)命令接触终于的servlet之前,会有一个长长的管道(SimplePipeline),管道里有一个一个的阀(Valve),每个阀都会做一个任务!就这么简单,在管道里面有一个基础阀(SimpleWrapperValve),而这个基础阀就用来生成servlet,调用其service方法。

wrapper程序的类图例如以下:
流程例如以下
先是调用wrapper的invoke;

SimpleWrapper.java  public void invoke(Request request, Response response)    throws IOException, ServletException {    pipeline.invoke(request, response);  }
再调用管道的invoke;
SimplePipeline.java    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);  }  SimplePipelineValveContext为SimplePipeline的内部类,作用就是循环全部的阀,最后调用基础阀(就是以下代码中的basic)  SimplePipelineValveContext.java   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("No valve");      }    }
 这部分的基础阀就是SimpleWrapperValve(在构造simplewrapper时就指定了),基础阀会调用反射生成servlet类......

 第二部分 context

 类图例如以下:

 绝大部分的web程序不可能仅仅有一个servlet,多个servlet就会构成一个context。
 换句话说,一个context里面有多个wrapper。
 那么如今就有问题了,多个wrapper总得有个记录,请求1应该让哪个wrapper来处理,请求2又该让哪个wrapper处理等等。

 因此就有了mapper接口,我们这里用的是事实上现类,simplecontextmapper。其map方法就能返回对应的wrapper。

public Container map(Request request, boolean update) {    String requestURI = ((HttpRequest) request).getDecodedRequestURI();    String relativeURI = requestURI.substring(contextPath.length());    Wrapper wrapper = null;    String name = context.findServletMapping(relativeURI);    if (name != null)      wrapper = (Wrapper) context.findChild(name);    return (wrapper);  }
  找到wrapper就和上一部分的过程一样了。

第六章 生命周期

第 6 章解释了 Lifecycle 接口。这个接口定义了一个 Catalina 组件的生命周期。并提供了一个优雅的方式。用来把在该组件发生的事件通知其它组件。另外。Lifecycle 接口提供了一个优雅的机制,用于在 Catalina 通过单一的 start/stop 来启动和停止组件。

本章类图:
tomcat是组件化的软件。全部的组件都实现了Lifecycle接口,里面有start与stop方法;我们如今想要的效果就是,我仅仅用启动一个组件系统就能帮我把全部的都启动,关闭也是一样。

看上去非常复杂,事实上非常easy

public synchronized void start() throws LifecycleException {    if (started)      throw new LifecycleException("SimpleContext has already started");    // Notify our interested LifecycleListeners    lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);    started = true;    try {      // Start our subordinate components, if any      if ((loader != null) && (loader instanceof Lifecycle))        ((Lifecycle) loader).start();      // Start our child containers, if any      Container children[] = findChildren();      for (int i = 0; i < children.length; i++) {        if (children[i] instanceof Lifecycle)          ((Lifecycle) children[i]).start();      }      // Start the Valves in our pipeline (including the basic),      // if any      if (pipeline instanceof Lifecycle)        ((Lifecycle) pipeline).start();      // Notify our interested LifecycleListeners      lifecycle.fireLifecycleEvent(START_EVENT, null);    }    catch (Exception e) {      e.printStackTrace();    }
SimpleContext里面的各个组件依次启动就ok;
事实上这一章假设仅仅是说生命周期的话到这就结束了,但是假设说到观察者模式,那话就多了。
所谓观察者模式,说的简单点就是,我有了一个动作,就要通知一些关心我的人。就这么简单。

Bootstrap.java    LifecycleListener listener = new SimpleContextLifecycleListener();    ((Lifecycle) context).addLifecycleListener(listener);simplecontext.javaprotected LifecycleSupport lifecycle = new LifecycleSupport(this);public void addLifecycleListener(LifecycleListener listener) {    lifecycle.addLifecycleListener(listener);  }
  执行时,以下的代码就是告诉全部关心SimpleContext的监听者:SimpleContext类做了BEFORE_START_EVENT这个动作!
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);LifecycleSupport.java  public void fireLifecycleEvent(String type, Object data) {        LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);        LifecycleListener interested[] = null;        synchronized (listeners) {            interested = (LifecycleListener[]) listeners.clone();        }        for (int i = 0; i < interested.length; i++)      //循环通知全部关注者            interested[i].lifecycleEvent(event);    }// 一个详细的关注者public class SimpleContextLifecycleListener implements LifecycleListener {  @SuppressWarnings("unused")public void lifecycleEvent(LifecycleEvent event) {    Lifecycle lifecycle = event.getLifecycle();    System.out.println("SimpleContextLifecycleListener's event " +event.getType().toString());    if (Lifecycle.START_EVENT.equals(event.getType())) {      System.out.println("Starting context.");    }    else if (Lifecycle.STOP_EVENT.equals(event.getType())) {      System.out.println("Stopping context.");    }  }}
你可能感兴趣的文章
oracle index contention,故障排除 | enq:TX - index contention等待事件
查看>>
silk v3 decoder php,解码转换QQ微信的SILK v3编码音频为MP3或其他格式
查看>>
延时关机命令 linux,windows定时关机和linux定时关机的方法(shutdown命令)
查看>>
linux内核最早延迟,工作队列是实现延迟的新机制,从2.5版本Linux内核开始提
查看>>
linux的操作命令文档,Linux文档操作命令
查看>>
linux不能访问80端口,lunux开放80端口(本地访问不了linux文件可能是这个原因)...
查看>>
linux max函数头文件,Linux下select函数
查看>>
linux无法挂载移动硬盘6,Linux下挂载移动硬盘
查看>>
linux查看与开启sshd服务,[转载]linux查看与开启sshd服务
查看>>
linux新建备份数据库的脚本文件在哪,linux数据库备份脚本
查看>>
kali linux中查看已安装软件,kali linux 怎么使用终端查看已安装软件
查看>>
linux svn仓库备份,linux SVN备份
查看>>
arm-linux-gcc /lib/libc.so.6,Cannot find /lib/libc.so.6
查看>>
linux从类型void*到类型data*的转换无效,从类型“MyStruct”到类型“void*”的强制转换无效...
查看>>
linux 英语大全对照表,Linux下推荐的常用应用程序列表(国外英语).doc
查看>>
2018秋c语言程序设计考试答案,2018秋C语言程序设计上(赵三元)-中国大学mooc-题库零氪...
查看>>
c语言从文件读取矩阵做乘积,三阶矩阵的乘法(C语言从文件中读入)
查看>>
爱因斯坦阶梯问题用while循环c语言,【C语言编程练习】5.9 爱因斯坦的阶梯问题...
查看>>
c语言软件横8,经典C语言程序设计100例(8)
查看>>
c语言结构体初始化及赋值,结构体的定义、初始化和赋值
查看>>