how tomcat works 总结 二

第五章 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方法;我们现在想要的效果就是,我只用启动一个组件系统就能帮我把所有的都启动,关闭也是一样。看上去很复杂,其实很简单

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.java
protected 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.");
    }
  }
}

时间: 2024-10-10 17:37:29

how tomcat works 总结 二的相关文章

攻城狮在路上(肆)How tomcat works(二) 一个简单的servlet容器

该节在上一节的基础上增加了所谓对静态资源和动态资源访问的不同控制流程.示例里面采用的是对路径“/servlet/”进行了特殊处理. 一. 主要还是从HttpServer1中的main方法开始,先解析出Request和Response对象,然后如果请求路径中包含/servlet/路径的话, 就进入ServletProcesser1进行处理,否则就进入StaticProcessor进行处理. 在ServletProcessor1中,对Request和Response进行了封装,通过URLClassL

《How Tomcat Works》读书笔记(二)

<How Tomcat Works>读书笔记(二) 这是<How Tomcat Works>第一二章的读书笔记.第一张主要写了一个静态资源处理的web服务器,第二章加了对servlet的处理. 1. 概述 1.1 架构 HttpServer:表示Http服务器,与客户端通信,处理Http请求. StaticResourceProcessor:对静态资源请求进行处理. ServletProcessor:对Servlet资源请求进行处理. Request:表示Http请求,实现了Ser

how tomcat works 读书笔记(二)----------一个简单的servlet容器

app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/article/details/39378157) 回顾我们上一章,我们开发了一个最最简单的web服务器,它可以使用户访问服务器内的静态资源.当然这是远远不够的,在这一节里,我们就试着让服务器在能相应静态资源的基础上继续支持servlet. servlet接口 javax.servlet.Servlet接口

How Tomcat works — 四、tomcat启动(3)

上一节说到StandardService负责启动其子组件:container和connector,不过注意,是有先后顺序的,先启动container,再启动connector,这一节先来看看container. 目录 Pipeline和Vavle StandardEngine类和StandardHost类 StandardContext类 总结 Pipeline和Vavle 在第二节(How Tomcat works — 二.tomcat启动(1))中没有介绍关于Pipeline和Vavle,因

how tomcat works

目标 深入剖析tomcat •Java Web 服务性能优化实践2014-11-04阅读225 •How Tomcat work之第十五章之Digester之setting property2014-07-30阅读253 •How Tomcat work 之第十四章之server and services 之application2014-07-29阅读194 •how tomcat work之第十四章:server and service2014-07-27阅读352 •How Tomcat

How Tomcat Works 2

上一节(How Tomcat Works 1 编写一个简单静态web服务器)编写了一个简单的web服务器,只能处理静态的资源,本节将继续向前迈出一个小步,创建两个不同的servlet容器,能够利用servlet简单的处理动态内容.注意每节的代码都是基于上一节的继续丰富,因此有必要从第一节开始看起. 在编写代码之前,需要先大体了解一下Servlet是什么,方便后面的理解,下面就是一个最简单的Servlet什么也没做: package prymont; import java.io.IOExcept

Tomcat剖析(二)

Tomcat剖析(二) 目录: Tomcat剖析(一):一个简单的Web服务器 Tomcat剖析(二):一个简单的Servlet服务器 这一节基于 <深度剖析Tomcat>第二章: 一个简单的Servlet服务器 总结而成. 上一节,我们了解了一个简单的Web服务器的总体处理流程是怎样的:这一节,我们开始搭建一个简单的Servlet容器,也就是增加实现了servlet的简单加载执行,而不仅仅是将文件内容输出到浏览器上.当然,这一节的servlet的实现是最简单的,用来了解整个Servlet的大

how tomcat works 读书笔记四 tomcat的默认连接器

其实在第三章,就已经有了连接器的样子了,不过那只是一个学习工具,在这一章我们会开始分析tomcat4里面的默认连接器. 连接器 Tomcat连接器必须满足以下几个要求 1 实现org.apache.cataline.Connector接口 2 负责创建实现了org.apache.cataline.Request接口的request对象 3 负责创建实现了org.apache.cataline.Response接口的response对象 这里默认的连接器的原理很简单,就是等待http请求,创建re

Tomcat学习之二:tomcat安装、配置及目录文件说明

我们看到tomcat目录/bin文件夹里有个tomcat6w.exe,顾名思义就是tomcat以window方式显示控制台.第1次点击打开它时候,可能会提示:tomcat指定的服务未安装,此时我们可以这样解决它. 打开命令行提示符窗口-> 进入Tomcat安装目录-> 进入bin目录下-> 输入:service.bat install 即可,如图操作,tomcat目录按自己电脑上的来即可 <!--[endif]--> 这样就可以让tomcat以window方式显示控制台.点击