没有人永远年轻,但永远有人年轻
之前手写了一个能解析Servlet的简单的Servlet容器,但是我们的目标可不能止于这些,把Tomcat写出来才是我们最终的目标~
- 相关代码已同步Github
概述
我们知道Catalina中有两个主要的板块,一个是connector,另外一个是container。
- 连接器负责将请求和容器关联,它为每一个Http请求创建一个request和response对象。然后把这两个对象交给容器
- 容器接收到对象之后,调用request请求的servlet的service方法。之后,把处理的结果以response返回回去
连接器主要类
相对于上一篇博客的服务器,我们把要写的类分为以下几个类型:
- 启动类:
Bootstrap - 连接器类
-
HttpConnector和HttpProcessor上一章是HttpServer-
HttpConnector等待Http请求 -
HttpProcessor创建HttpRequest和HttpResponse实例
-
-
HttpRequest和其支持类 上一章是Request -
HttpResponse和其支持类 上一章是Response - Http的外观类(之前已经实现过)
- 常量类
-
HttpHeader主要用于解析请求头 -
HttpRequestLine主要用于解析请求行 -
Constants主要是路径
-
-
- 核心模块
ServletProcessorStaticResourceProcessor
处理流程
本程序的服务器流程是:
- 先是
Boostrap启动服务器,然后HttpConnect等待客户端的请求。 - 当请求到达时,服务器会新开一个线程接收该请求,拿到
socket后,把socket传给HttpProcessor,同时HttpProcessor处理该socket。 -
HttpProcessor会执行四个操作,创建HttpRequest对象和HttpResponse对象,解析Http请求的请求行和请求头信息,填充HttpRequest对象。 -
HttpRequest会去获得参数,而不是通过HttpProcessor来获取,因为我们不知道servlet是否需要这些参数,这样可以减少资源消耗 - 之后,将
HttpRequest对象和HttpResponse对象传递给ServletProcessor或者StaticResourceProcessor的process()方法。对于前者来说,其process方法会先找到自定义的Servlet类,然后调用其service方法;对于后者说,其process方法会直接读取静态文件。 - 之后,把内容填充到
HttpResponse中,返回给客户端
UML类图
其中,
org.apache.catelina.util.StringManager类用于处理不同模块的错误消息和国际化操作
- 同一个包下的类共用一个StringManager实例 通过单例模式实现
- 每个包使用一个
properties来说明该包中任何类可能出现的异常信息,每个异常信息都是kv的形式