Tomcat的管道(Pipeline)机制以及Context,Wrapper容器
Posted 占用我名字
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tomcat的管道(Pipeline)机制以及Context,Wrapper容器相关的知识,希望对你有一定的参考价值。
最近学习了Tomcat,所以想把自己学到的东西总结记录一下,不紧是自己消化的过程,同时也希望帮助更多的人更好的去理解Tomcat的内部原理。因为博主看的是《深入剖析Tomcat》这本书,所以讲述的都以Tomcat4为标准,我认为理解了Tomcat4,后面的版本也会很容易去理解。
这次主要总结下Tomcat的管道(Pipeline)机制以及Context,Wrapper容器,其实tomcat简单的来说可以有两部分组成,一个就是连接器(Connector)和容器(container),如下图。连接器就是负责跟浏览器也就是客户端连接。容器也就是Servlet容器,用来负责跟Servlet有关的操作,Servlet也就是我们JAVA WEB中常常写的那个Servlet。因为这次主要总结的内容是跟容器有关,所以就简单的说一下连接器。
1、连接器
连接器主要是负责跟浏览器建立连接,其实连接器的原理是Socket编程,Socket大家应该并不陌生。就是浏览器过来一个请求,就接收这个请求,然后连接器会分配一个线程去处理这个请求。因为tomcat是用java编写的,所以所谓的连接器就是一些JAVA类。大家对HTTP请求格式应该有所了解,如下图。
当在地址栏输入个地址,浏览器就以上面的格式向Tomcat发送信息,Tomcat的Socket是以String形式接收到上面的信息,然后连接器就开始创建Request,Response对象,接着解析上述的信息,也就是对一些字符串的操作。把解析到的数据放入request对象的变量中。当这些操作完毕后,就把Request跟Response对象传给容器。从连接器到容器的简单步骤就完成。
2、容器
容器主要是用来负责调用Servlet,同时也有很多组件,例如载入器,主要是负责把这些Servlet先载入,到时候容器调用对应的Servlet的时候,直接从载入器取得。Tomcat中有四个容器,分别是Engine,Host,context,Wrapper。级别是从大到小的。context表示一个Web应用程序,Wrapper表示一个Servlet。一个Web应用程序中可能会有多个Servlet。Host代表的是一个虚拟主机,就好比你的一个Tomcat下面可能有多个Web应用程序。同时Engine是Host的父类,Host是Context的父类,Context是Wrapper父类。他们之间的关系如下图
每个容器都实现了Container接口,上图中的虚线表示implement,实线表示extends。我举一个简单的例子来说明下Context跟Wrapper的区别。
假如你有一个Web程序,其中有两个Servlet ,两个Servlet在web.xml配置文件中如下。
<?xml version="1.0"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <welcome-file-list> <welcome-file>/index.html</welcome-file> </welcome-file-list> <servlet> <servlet-name>MyFirstServlet</servlet-name> <servlet-class>MyFirstServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyFirstServlet</servlet-name> <url-pattern>/MyFirstServlet</url-pattern> </servlet-mapping>
</servlet>
此时就会创建两个Wrapper,创建一个Context对象。类似于如下的代码:
<servlet> <servlet-name>MySecondServlet</servlet-name> <servlet-class>MySecondServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MySecondServlet</servlet-name> <url-pattern>/MySecondServlet</url-pattern> </servlet-mapping>
</web-app></servlet>
Wrapper wrapper1 =new StandardWrapper();
wrapper1.setName("MyFirstServlet"); //上面配置文件中的<servlet-name>里面的内容
wrapper1.setServletClass("MyFirstServlet"); //上面配置文件<servlet-class>里面的内容
Wrapper wrapper2 =new StandardWrapper();
wrapper2.setName("MySecondServlet");
wrapper2.setServletClass("MySecondServlet");
Context context =new StandradContext(); //创建父类
context.addChild(wrapper1);
context.addChild(wrapper2);
context.addServletMapping("/MyFirstServlet","MyFirstServlet"); //第一个参数就是上面配置文件的<url-pattern>,第二个参数对应的是wrapper的名称
context.addServletMapping("/MySecondServlet","MySecondServlet");
假设你的一个请求为如下:http://localhost:8080/MyApp/MyFirstServlet (其中MyApp为你的Web应用名)
Tomcat的连接器处理完这些请求后,会调用父容器context,同时把request,respone 传给context容器,容器根据你请求的URL,也就是/MyFirstServlet ,得到对应的Wrapper,Wrapper中又可以找到对应的ServletClass,然后通过这个名称在载入器中找到对应的Servlet类,然后调用Servlet的service方法。这就是大概的过程。接下来总结下Tomcat的管道机制。
大家应该都知道java web 的过滤器,其实管道机制就类似于过滤器。当连接器处理完请求后开始调用容器,从容器的一系列处理到调用对应的Servlet之间,会调用管道机制处理一系列的请求。其实类似于如下图所示
中间的那一部分就类似与管道,而管道中的每一个阀就是一个JAVA类,也就是容器到调用对应的Servlet过程中要进入这个管道,然后调用管道中的阀。管道中有一个基础阀,这个基础阀是在上面的所有阀调用完成以后再调用。其中就是基础阀跟Servlet进行连接,如果前面的阀只是对Requset进行一些处理的话,那么基础阀会根据请求的URL调用对应的Servlet的Service方法。
在前面讲第二小节刚开始给说了容器之间的UML类图,其实tomcat的四个容器都继承自ContainerBase。而ContainerBase这个类,实现了Pipeline这个借口。Pipeline就是管道。Pipeline的接口如下
public interface Pipeline
public Valve getBasic(); //得到基础阀
public void setBasic(Valve valve); //设置基础阀
public void addValve(Valve valve); //增加阀
public Valve[] getValves(); //得到所有的阀(不包括基础阀)
public void invoke(Request request, Response response)
throws IOException, ServletException; //这个方法就是用来进行调用每个阀。
public void removeValve(Valve valve);
其实ContainerBase中还有一个变量如下
protected Pipeline pipeline = new StandardPipeline(this);
StandardPipeline是Pipeline的实现类。 因为ContainerBase实现了Pipeline接口。所以ContainerBase会实现invoke方法。如下:
public void invoke(Request request, Response response)
throws IOException, ServletException
pipeline.invoke(request, response); //这个方法就是调用管道的invoke方法,然后开始处理管道中的一系列阀,最后处理基础阀。在基础阀中调用对应的Servlet.
从前面知道连接器处理完连接后,会调用Servlet容器。其实调用的就是Servlet容器的invoke方法,然后处理管道中的一系列阀,最后调用对应的Servlet.
本次主要总结了管道机制在一次请求的流程中是如何被应用到了,并没有更深的总结代码上面的东西,先了解下tomcat的运行机理,然后再看代码可能会更加容易一些。
这是博主第一次写博客,如果有些地方写的不够合理或者不对的地方,希望大家可以及时告诉我。总结的不是很好,希望大家笑纳。
以上是关于Tomcat的管道(Pipeline)机制以及Context,Wrapper容器的主要内容,如果未能解决你的问题,请参考以下文章