Tomcat工作原理

来源:互联网 发布:乐思网络信息采集系统 编辑:程序博客网 时间:2024/06/09 05:08

Tomcat工作原理

Tomcat 是最常用的 JSP/Servlet 容器。Tomcat的结构实际上非常复杂,这里只选择其中的几个核心组件加以说明。

Tomcat总体结构


从上图可以看出,Tomcat的2个最核心的组件就是Connector连接器和Container容器。一个Container可以对应选择多个Connector。多个 Connector 和一个 Container 就形成了一个 Service,有个Service就可以对外提供服务了。Tomcat就是一个Server服务器,它里面可以包含多个Service服务。

Server服务器

每启动一个Tomcat,实际上就是启动了一个Server服务器实例,它监听一个端口以接收shutdown命令。在同一台物理机器上启动多个Server,必须配置它们使用不同的端口。不过基于安全考虑,一台机器上我们一般只会启动一个Server服务器。一个Server中可以包含多个Service服务。Server 要完成的任务很简单,就是要能够提供一个接口让其它程序能够访问到这个 Service 集合、同时要维护它所包含的所有 Service 的生命周期,包括如何初始化、如何结束服务、如何找到别人要访问的 Service。

Service服务

多个 Connector 和一个 Container 就形成了一个 Service。其中,Connector组件主要负责对外交流,Container组件则是处理来自Connector接收的请求。说白了,Service中封装了Connector和Container,然后向外提供服务。一个Service可以设置多个Connector连接器,但是只能有一个Container容器。Service接口的方法列表如下:

从Servicce接口中定义的方法也可以看出,Service关联了Connector和Container,同时会初始化它下面的其它组件。Service接口的标准实现类是StandardService,它不仅实现了Service接口,同时还实现了LifeCycle接口。LifeCycle用来控制所有组件的生命周期。

Connector连接器

Connector的主要任务是负责接收浏览器发送过来的Tcp请求,然后创建一个Request请求对象和Response响应对象(依据不同的协议会创建对用的Request和response)。Request中封装了浏览器的请求信息,Response中封装了反馈给浏览器的响应信息。之后,会产生一个线程来处理这个请求并把产生的 Request 和 Response 对象传给处理这个请求的线程任务,处理这个请求的线程就是 Container 组件要做的事了。

Container组件

Container 是容器的父接口,所有子容器都必须实现这个接口。它有四个子容器组件构成,分别是:Engine、Host、Context、Wrapper,这四个组件不是平行的,而是父子关系,Engine 包含 Host,Host 包含 Context,Context 包含 Wrapper。通常一个 Servlet class 对应一个 Wrapper,如果有多个 Servlet 就可以定义多个 Wrapper。

Engine组件

Engine是Servlet处理器的一个实例,即servlet引擎。

Host组件

Host 是 Engine 的字容器,一个 Host 在 Engine 中代表一个虚拟主机,这个虚拟主机的作用就是运行多个应用,它负责安装和展开这些应用,并且标识这个应用以便能够区分它们。它的子容器通常是 Context,它除了关联子容器外,还有就是保存一个主机应该有的信息。

Context组件

Context 就是 Servlet 的容器,它具备了 Servlet 运行的基本环境,理论上只要有 Context 就能运行 Servlet 了。简单的 Tomcat 可以没有 Engine 和 Host。
Context 最重要的功能就是用于标识tomcat实例中的一个Web应用程序(Servlet程序),Servlet 实例在 Context 中是以 Wrapper 出现的。

Wrapper组件

Wrapper 代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。

Tomcat的启动过程

创建一个Tomcat实例对象并调用 start 方法就可以很容易启动 Tomcat,我们还可以通过这个对象来增加和修改 Tomcat 的配置参数,如可以动态增加 Context、Servlet 等。下面我们就利用这个 Tomcat 类来管理新增的一个 Context 容器,我们就选择 Tomcat7 自带的 examples Web 工程,并看看它是如何加到这个 Context 容器中的。

Tomcat tomcat = getTomcatInstance(); //创建一个Tomcat对象//将应用程序的路径封装成一个File对象File appDir = new File(getBuildDirectory(), "webapps/examples"); //通过tomcat的addWebAPP()方法,新增一个Web应用到Tomcat中tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath()); //启动Tomcattomcat.start(); //调用其中的一个HelloWorldExample ServletByteChunk res = getUrl("http://localhost:" + getPort() +               "/examples/servlets/servlet/HelloWorldExample"); assertTrue(res.toString().indexOf("<h1>Hello World!</h1>") > 0);

Tomcat 的 addWebapp 方法的代码如下:

public Context addWebapp(Host host, String url, String path) {        silence(url);        Context ctx = new StandardContext(); //创建一个Context对象       ctx.setPath( url ); //设置Context的路径       ctx.setDocBase(path);        if (defaultRealm == null) {            initSimpleAuth();        }        ctx.setRealm(defaultRealm);        ctx.addLifecycleListener(new DefaultWebXmlListener());        ContextConfig ctxCfg = new ContextConfig();        ctx.addLifecycleListener(ctxCfg); //创建ContextConfig对象       ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML");        if (host == null) {            getHost().addChild(ctx);        } else {            host.addChild(ctx); //将Context对象添加到一个host中       }        return ctx; }

一个web应用对应一个Context容器,也就是Servlet运行时的Servlet容器。添加一个web应用时会创建一个StandardContext容器,并且会给这个容器设置必要的参数。ContextConfig对象会负责整个web应用配置的解析。最后将这个Context容器添加到父容器Host中。

Tomcat的请求过程

这里写图片描述
1. Tomcat服务器的Connector对象负责与浏览器建立TCP连接。当一个浏览器向服务器发送请求时,该请求就会被HttpConnector接收。HttpConnector创建轻量级对象Request和Response。

  1. HttpConnector将Request和Response传递给Container容器进行处理。首先就是根据request快速检索出对应的Servlet对象;这里用到了org.apache.tomcat.util.http.mapper类,这个类保存了 Tomcat 的 Container 容器中的所有子容器的信息,因此Mapper可以立马检索出这个请求对应的servlet。

  2. 如果请求的Servlet不存在,Servlet容器就会通过反射创建这个Servlet对象,并调用init()初始化该对象。然后Servlet添加到对应的ServletContext容器中。

  3. 在ServletContext中,首先依据Request和Response的内容创建ServletRequest 和 ServletResponse对象。然后将ServletRequest和ServletResponse作为参数,调用Servlet的service()方法。在service()方法中,根据请求的类型会调用对应的doxxx()方法。执行业务逻辑、数据存储等程序。

  4. service()方法执行完成之后,Context将HttpServletResponse对象返回给Host。

  5. Host把HttpServletResponse对象返回给Engine。

  6. Engine把HttpServletResponse对象返回Connector。
  7. Connector把Response对象的内容响应给客户Browser。
原创粉丝点击