几乎从一接触java就接触了tomcat,可是这只猫到底是怎么工作的一直也没时间研究,今天开始好好研究一下,第一次写,先拿这里当个记录的地方,说的比较乱,主要是用来存点乱七八糟的东西。
先抄一段tomcat的启动定义
1.调用在Bootstrap中的主函数main()程序入口调用自身的start()方法,在start()方法中实例化org.apache.catalina.startup.Catalina类调用其start()方法,在Catalina的start()中调用load()载入tomcat文件夹目录下conf文件夹下的server.xml并创建Server类,然后调用Server的start()方法,到这里我们的tomcat就运行起来了.
2.Server类代表整个Tomcat服务器,这里有必要介绍一下为什么Tomcat叫Servlet容器,在Tomcat中包含四个容器,分别为Engine,Host,Context,Wrapper.Engine是Host的父容器,依次类推.四者都继承自Container接口.一般在Tomcat中一个Engine实例中包含一个Host实例,一个Host实例中包含一个Context实例,一个Context代表一个WEB程序并包含多个Wrapper实例,一个Wrapper代表一个Servlet类.
3.一次请求的大题流程是这样的,首先由Connector获取到Http请求,封装ServletRequest和ServletResponse对象并派发给Context管道中的所有Valve,执行完所有Valve后执行基础Valve根据请求的url映射到对应的Wrapper,然后调用个Wrapper管道中的所有Valve,最后调用基础Valve在如这个Wrapper类所封装的Servlet,实例化后调用器Service方法对用户的请求进行处理,最后将结果负载在response中返回给用户.
给张图看看吧(百度上找的,不知道原创是谁,这里就不写出处了)
接着看看tomcat的目录:
tomcat
|---bin:存放启动和关闭tomcat脚本
|---conf:存放不同的配置文件(server.xml和web.xml);
|---doc:存放Tomcat文档;
|---lib/japser/common:存放Tomcat运行需要的库文件(JARS);
|---logs:存放Tomcat执行时的LOG文件;
|---src:存放Tomcat的源代码;
|---webapps:Tomcat的主要Web发布目录(包括应用程序示例);
|---work:存放jsp编译后产生的class文件;
conf先看这个
server.xml,这个配置文件和上图相呼应,很重要的一个配置文件
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JasperListener" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="80" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="gaopin-admin" debug="0" reloadable="true"/>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
这是我删掉注释以后的server.xml文件,是不是看着清爽多了?
结合第一张图说说,Server、Service、Connector、Engine、Host、Context
Server--是Tomcat最顶层的容器
<Server port=”8005” shutdown=”SHUTDOWN”> 第一行就是个shutdown,前面还有个Server 这意思很明白了,关闭这个Server。
目前水平只能说这么多了,下边的Listener监听的包是啥先不管了,还有那个GlobalNamingResources,百度了一下,好像是连接数据库的,也先不管了
Service--用于提供服务
<Service name=”Catalina”> 这里定义了一个Service的name
Connector--用于处理连接相关的事情,并提供Socket与request和response的转换
这里默认有2个连接器,一个是80端口是http的,一个是8009端口的AJP的
日常能用到的是那个80端口的http的连接器,这里只说这个
<Connector port="80" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
这是默认参数,其中port(端口)是必须的,其他参数是可选的,其他参数还有
1) address:指定连接器监听的地址,默认为所有地址,即0.0.0.0; 可以自己指定地,如
2) maxThreads:支持的最大并发连接数,默认为200;
3) port:监听的端口,默认为0;
4) protocol:连接器使用的协议,默认为HTTP/1.1,定义AJP协议时通常为AJP/1.3;
5) redirectPort:如果某连接器支持的协议是HTTP,当接收客户端发来的HTTPS请求时,则转发至此属性定义的端口;
6) connectionTimeout:等待客户端发送请求的超时时间,单位为毫秒,默认为60000,即1分钟;
7) enableLookups:是否通过request.getRemoteHost()进行DNS查询以获取客户端的主机名;默认为true; 进行反解的,可以设置为false
8) acceptCount:设置等待队列的最大长度;通常在tomcat所有处理线程均处于繁忙状态时,新发来的请求将被放置于等待队列中;
Engine--用于封装和管理Servlet,以及具体处理request请求
<Engine name=”Catalina” defaultHost=”localhost”> Engine是Servlet处理器的一个实例,即servlet引擎,默认为定义在server.xml中的Catalina。Engine需要defaultHost属性来为其定义一个接收所有发往非明确定义虚拟主机的请求的host组件。这里一般都是一个host。
Engine容器中可以包含Realm、Host、Context和Valve子容器。
Realm--和上面那个连接数据库用的差不多,生产里不用,这里就研究了
Host--位于Engine容器中用于接收请求并进行相应处理的主机或虚拟主机
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
</Host>
常用属性说明
1) appBase:此Host的webapps目录,即存放非归档的web应用程序的目录或归档后的WAR文件的目录路径;可以使用基于$CATALINA_HOME的相对路径;
2) autoDeploy:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy;默认为true;
3) unpackWars:在启用此webapps时是否对WAR格式的归档文件先进行展开;默认为true;
appBase就是存放WAR包的位置
Context--一个Context定义用于标识tomcat实例中的一个Web应用程序
<Context path="" docBase="gaopin-admin" debug="0" reloadable="true"/>
其实这里可以配置多个,但是一般生产环境里为了稳定,多为配置一个
常用参数说明
1) docBase:相应的Web应用程序的存放位置;也可以使用相对路径,起始路径为此Context所属Host中appBase定义的路径;切记,docBase的路径名不能与相应的Host中appBase中定义的路径名有包含关系,比如,如果appBase为deploy,而docBase绝不能为deploy-bbs类的名字;
2) path:相对于Web服务器根路径而言的URI;如果为空“”,则表示为此webapp的根路径;如果context定义在一个单独的xml文件中,此属性不需要定义,有可能是别名;
3) reloadable:是否允许重新加载此context相关的Web应用程序的类;默认为false;
Valve--类似于过滤器
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
这里默认是配置日志的,百度了一下,这个Valve还可以配置tomcat集群,认证,远程访问等等,由于用不到,所以就不研究了
梳理一下,用户请求的流程:
1、用户点击网页内容,请求被发送到本机端口80,被在那里监听的Coyote HTTP/1.1 Connector获得。
2、Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应。
3、Engine获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host。
4、Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机),名为localhost的Host获得请求/test/index.jsp,匹配它所拥有的所有的Context。Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为“ ”的Context去处理)。
5、path=“/test”的Context获得请求/index.jsp,在它的mapping table中寻找出对应的Servlet。Context匹配到URL PATTERN为*.jsp的Servlet,对应于JspServlet类。
6、构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost().执行业务逻辑、数据存储等程序。
7、Context把执行完之后的HttpServletResponse对象返回给Host。
8、Host把HttpServletResponse对象返回给Engine。
9、Engine把HttpServletResponse对象返回Connector。
10、Connector把HttpServletResponse对象返回给客户Browser。