How Tomcat Works读书笔记

首先明确Tomcat的职责是什么,也就是说Tomcat做了哪些事情?
我觉得下面几件事情是Tomcat必须要做的比较重要的事情。

  1. 监听某个端口,捕获HTTP请求。
  2. 将HTTP请求转换为相应的Request对象,当然也应该需要创建一个Response对象
  3. 然后初始化一个Servlet对象,或者说加载一个Servlet对象,将相应的Request对象和Response对象传递进去,之后调用Servlet中的service函数。

Tomcat的架构图

Tomcat的架构图.png

上面一张图片比较详细,下面放一张简单一点的架构图。

imgr.jpg

Tomcat的架构浅析

通过图片可以看到Tomcat是分成好几个模块的。最外面是一个Server,一个Server可以有好几个Service服务,一个Service服务会有几个Connector组件,但是只会有一个Container组件,另外还有好几个不是那么核心的组件,比如说管理Session的组件,写日志的组件。

其中也提到了最核心的组件(Component)就是ConnectorContainer

Connector的作用就是监听某一个端口,然后接受HTTP请求,将HTTP请求封装成Servlet需要使用的HttpServletRequest对象和HttpServletResponse对象。也就是说将纯文本的Http请求解析出来了之后变成可以方便使用的Request对象,而Response对象需要作为一个返回值的容纳地,也是需要传递给Servlet*的。

Container的作用就是根据Request中URL中的信息加载相应的Servlet对象,之后就是调用相应的方法,讲结果封装在Response对象中,最后当然也是转换为HTTP的文本返回给客户端。

A Simple Servlet Container

当有了基本的架构概念了之后,我觉得可以直接看一些简单的小例子,来看一下在代码中这些组件是如何关联作用在一起的,下面就把How Tomcat Works中的一个第五章中的小例子贴出来。(其实前面几个章节有更加简单的例子,感兴趣的可以看下。)

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 ex05.pyrmont.valves.HeaderLoggerValve;
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,每一个实例里面都是会有一个Servlet的
    Wrapper wrapper1 = new SimpleWrapper();
    //设置Servlet的映射地址
    wrapper1.setName("Primitive");
   //设置Servlet的名字
    wrapper1.setServletClass("PrimitiveServlet");
    Wrapper wrapper2 = new SimpleWrapper();
    wrapper2.setName("Modern");
    wrapper2.setServletClass("ModernServlet");
 
    //context是一个容器可以包含wrapper这个最底层的容器
    Context context = new SimpleContext();
    context.addChild(wrapper1);
    context.addChild(wrapper2);

    Valve valve1 = new HeaderLoggerValve();
    Valve valve2 = new ClientIPLoggerValve();
    //容器中除了其他容器之外还有Valve
    //另外要注意的是每一个context都是实现了Pipeline和Context接口的
    ((Pipeline) context).addValve(valve1);
    ((Pipeline) context).addValve(valve2);
    //这个mapper是做什么的呢?
    Mapper mapper = new SimpleContextMapper();
    mapper.setProtocol("http");
    context.addMapper(mapper);
    Loader loader = new SimpleLoader();
    //容器中还需要加载器,通过反射加载真正的Servlet对象
     context.setLoader(loader);
    // context.addServletMapping(pattern, name);
   //context里面初始化了一个HashMap,存储映射和Servlet名字
    context.addServletMapping("/Primitive", "Primitive");
    context.addServletMapping("/Modern", "Modern");
    //因为connector封装好Reqeust之后会调用容器,所以将容器的声明给Connector
    connector.setContainer(context);
    try {
      connector.initialize();
       //connector开始监听端口,要明白底层肯定使用ServerSocket来实现的
      connector.start();

      // make the application wait until we press a key.
      System.in.read();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

BootStrap是一个Tomcat启动的程序入口。可以看到源代码中初始化了这么几个对象,一个HttpConnector,两个Wrapper,一个Context,两个Valve,一个Loader等,具体可以看注释,还是把我的理解写在注释里面把。

再看一张图

host_context_wrapper之间的关系.jpg

从第一张架构图中可以看到container是分成下面几个容器的,engine,host,context,wrapper。关系是这样的一个engine是可以有零个或者多个host的,以此类推。

那么这些容器的作用是什么呢?其实是用来匹配相应的URL,也就是讲一个请求的URL来分成者三个部分,最后找到要请求的Servlet。也就是说request是不断地在容器中传递的。其实容器中还有一个叫做Pipeline的东西,暂时还是不是很明白这个东西的作用是什么,每一个Pipeline都有很多的Valve。(有一点是这样的,Pipeline其实和过滤器是一个很像的东西)

ServletContext在哪里呢?

其实就是StandardContext中的一个全局变量。
Tomcat8.0.37中StandardContext.java部分源码

public class StandardContext extends ContainerBase
        implements Context, NotificationEmitter
    /**
     * The ServletContext implementation associated with this Context.
     */
    protected ApplicationContext context = null;
    /**
     * Return the servlet context for which this Context is a facade.
     */
    @Override
    public ServletContext getServletContext() {

        if (context == null) {
            context = new ApplicationContext(this);
            if (altDDName != null)
                context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
        }
        return (context.getFacade());

    }

最后

其实现在如果是用Springmvc这个框架的话,其实只是在web.xml中配置了一个拦截所有请求的前端Servlet,但是之后的事情比如Controller之类的东西都是Sringmvc在做了,而不是最原始的一个请求对应一个Servlet了。

最后的最后

因个人能力有限,以上内容肯定会有错误,所有欢迎交流讨论,另外如果觉得有帮助,可以点击一个喜欢,将这篇文章献给以后的自己和看到最后的你。

参考

JavaWeb学习之Servlet(四)----ServletConfig获取配置信息、ServletContext的应用

Tomcat容器结构及Pipeline机制 -我们到底能走多远系列(13)
tomcat架构分析概览
粗浅看 Tomcat系统架构分析
How do servlets work? Instantiation, sessions, shared variables and multithreading
Tomcat源码分析之容器整体结构

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,306评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,657评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,928评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,688评论 0 220
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,105评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,024评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,159评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,937评论 0 212
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,689评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,851评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,325评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,651评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,364评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,192评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,985评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,154评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,955评论 2 279

推荐阅读更多精彩内容