一、tomcat目录结构
tomcat也是一个应用服务器,下载tomcat源码可以看到tomcat的源码目录如下:
/bin、/conf、/webapps 这些目录就是在我们本地的安装目录可以看到的工具、配置、部署目录,/java目录就是具体的代码实现了
二、tomcat请求处理基本框架
tomcat是个很庞大的项目,这里只会涉及到请求处理部分,并且不涉及具体细节。
注:了解tomcat的大致结构可以先去看下tomcat安装目录中的conf/server.xml文件,文章末尾有样例。
首先,不管是tomcat还是什么其他的web服务器容器,基本功能一定都是监听请求、接受并处理请求,tomcat也是,核心在于请求监听与请求处理。
涉及的接口主要有:
1、Lifecycle
它算是tomcat最顶层的接口,从代码可以看出接口中定义了tomcat的整个生命周期状态一起一些生命周期函数。
package org.apache.catalina;
public interface Lifecycle {
// ----------------------------------------------------- Manifest Constants
/**
* The LifecycleEvent type for the "component before init" event.
*/
public static final String BEFORE_INIT_EVENT = "before_init";
public static final String AFTER_INIT_EVENT = "after_init";
public static final String START_EVENT = "start";
public static final String BEFORE_START_EVENT = "before_start";
public static final String AFTER_START_EVENT = "after_start";
public static final String STOP_EVENT = "stop";
public static final String BEFORE_STOP_EVENT = "before_stop";
public static final String AFTER_STOP_EVENT = "after_stop";
public static final String AFTER_DESTROY_EVENT = "after_destroy";
public static final String BEFORE_DESTROY_EVENT = "before_destroy";
public static final String PERIODIC_EVENT = "periodic";
public static final String CONFIGURE_START_EVENT = "configure_start";
public static final String CONFIGURE_STOP_EVENT = "configure_stop";
// --------------------------------------------------------- Public Methods
public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
public void init() throws LifecycleException;
public void start() throws LifecycleException;
public void stop() throws LifecycleException;
public void destroy() throws LifecycleException;
public LifecycleState getState();
public String getStateName();
public interface SingleUse {
}
}
这里重点注意start() 和 stop() 这两个函数,tomcat作为服务器来处理客户端请求,底层也是通过监听socket端口来建立socket连接,然后对请求进行一步步处理的,这里的start() 和 stop() 函数就是用来进行一些开始和结束的操作,包括初始化和终止 socket监听。
2、Connector
tomcat通过Connector来建立socket端口监听,进而接受外部请求进行处理。
说到通过端口来监听socket连接,这就和我们经常接触的tomcat安装目录下的server.xml配置联系起来了,下面是里面的部分配置信息:
可以看出在Connector标签中配置了监听的端口号以及其他一些信息,这个Connector在服务器的代码实现中也有对应的处理类,就是前面说的Connector类。
从server.xml可以理解每个Connector是作为一个连接器,每个Connector对象会监听一个端口,Connector类继承自Lifecycle 接口,监听端口的初始化操作也就在start()方法中实现:
在Connector连接器配置监听的过程中主要有个需要注意的接口ProtocolHandler:
从命名可以看出它是不同协议请求的处理接口,下面是它的所有实现类:
ProtocolHandler由包含了三个部件:Endpoint、Processor、Adapter。
Endpoint用来处理底层Socket连接
Processor用于将Endpoint接收到的Socket封装成Request
Adapter充当适配器,用于将Request转换为ServletRequest交给Container进行具体的处理。
如AbstractEndpoint:它里面封装了socket连接的处理逻辑,下面是它的所有实现类,目前最新版的tomcat都使用NIO的方式。
3、Container
Server.xml中的整个Engine即Container。
Connector进行请求监听,Container是进行连接建立后的请求处理的,它的实现类ContainerBase同样实现了Lifecycle 接口,所以在应用开始时ContainerBase也会执行其start()方法
与Container相关的概念有Engine、Host、Context、Wrapper
Engine:服务器引擎,对应一个Container,用于处理请求,其中可以包含多个Host
Host:主机,服务器,我们通过主机名+端口号访问我们的应用,主机就是这里的Host,其中包含多个Context
Context:一个应用上下文,即webapps目录下的一个项目
Wrapper:是对Context中处理请求的Servlet的封装
***附录:tomcat中默认的server.xml:
//Server代表一个tomcat应用服务器
//Service中包含了多个Connector和一个Container(即Engine),
相当于将两者封装起来表示这些Connector监听的请求由该Engine处理
//服务器引擎,对应源码中的Container,用于处理请求,其中可以包含多个Host,
默认是localhost,也就是说还可以配置其他域名的请求由该服务器处理?
我们通过主机名+端口号访问我们的应用,主机名就是这里的localhost。