Tomcat 之手写连接器

没有人永远年轻,但永远有人年轻

之前手写了一个能解析Servlet的简单的Servlet容器,但是我们的目标可不能止于这些,把Tomcat写出来才是我们最终的目标~

概述

我们知道Catalina中有两个主要的板块,一个是connector,另外一个是container

  • 连接器负责将请求和容器关联,它为每一个Http请求创建一个request和response对象。然后把这两个对象交给容器
  • 容器接收到对象之后,调用request请求的servlet的service方法。之后,把处理的结果以response返回回去

连接器主要类

相对于上一篇博客的服务器,我们把要写的类分为以下几个类型:

  • 启动类:Bootstrap
  • 连接器类
    • HttpConnectorHttpProcessor 上一章是HttpServer
      1. HttpConnector等待Http请求
      2. HttpProcessor创建HttpRequestHttpResponse实例
    • HttpRequest和其支持类 上一章是Request
    • HttpResponse和其支持类 上一章是Response
    • Http的外观类(之前已经实现过)
    • 常量类
      1. HttpHeader 主要用于解析请求头
      2. HttpRequestLine 主要用于解析请求行
      3. Constants 主要是路径
  • 核心模块
    • ServletProcessor
    • StaticResourceProcessor

处理流程

本程序的服务器流程是:

  1. 先是Boostrap启动服务器,然后HttpConnect等待客户端的请求。
  2. 当请求到达时,服务器会新开一个线程接收该请求,拿到socket后,把socket传给HttpProcessor,同时HttpProcessor处理该socket。
  3. HttpProcessor会执行四个操作,创建HttpRequest对象和HttpResponse对象,解析Http请求的请求行和请求头信息,填充HttpRequest对象。
  4. HttpRequest会去获得参数,而不是通过HttpProcessor来获取,因为我们不知道servlet是否需要这些参数,这样可以减少资源消耗
  5. 之后,将HttpRequest对象和HttpResponse对象传递给ServletProcessor或者StaticResourceProcessorprocess()方法。对于前者来说,其process方法会先找到自定义的Servlet类,然后调用其service方法;对于后者说,其process方法会直接读取静态文件。
  6. 之后,把内容填充到HttpResponse中,返回给客户端

UML类图

Tomcat 之手写连接器

其中,

org.apache.catelina.util.StringManager类用于处理不同模块的错误消息和国际化操作

  • 同一个包下的类共用一个StringManager实例 通过单例模式实现
  • 每个包使用一个properties来说明该包中任何类可能出现的异常信息,每个异常信息都是kv的形式