Tomcat的结构和对请求的处理
起因是装开发环境。
工程是javaEE的,基于maven管理依赖,开发工具是eclipse和tomcat。
工程怎么搞都启动出错,最后发现是该工程的web.xml中定义了自己的defaultservlet和jspservlet。
而tomcat启动的时候,会首先读取conf/web.xml下的定义,两者之间肯定要有一个被comment掉。
tomcat玩了这么多年,有必要把东西理一遍。
2. Tomcat的大结构
tomcat启动之后,将作为一个运行于JVM上的进程存在。
tomcat从层次上,最外围是server本身。
然后server里可以有多个service。每个service可以监听几个不同的端口号。
接下来,每个service里有多个connector。不同的connector监听不同的端口好,使用不同的通信协议。多个connector连接同一个container,container管辖多个webapp。
所有的这一切都定义在server.xml中。
- <!—最高节点
8005端口是shudown shell用端口号--> - <Server
port="8005" shutdown="SHUTDOWN"> - //JNDI全局资源
- <GlobalNamingResources>
- //service,可以有多个
- <Service
name="Catalina"> - //connector
我们一般都是用8080端口的http请求 - <Connector
connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/> - //每个connector都可以定义自己的线程池
- <Connector
executor="tomcatThreadPool" -
port="8080" protocol="HTTP/1.1" -
connectionTimeout="20000" -
redirectPort="8443" /> - //处理请求的容器
- <Engine
defaultHost="localhost" name="Catalina"> - //cluster配置
- <Cluster
className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> - //虚拟主机,可以定义多个虚拟主机。比如www.aaa.com,www.bbb.com,全部映射到同一个容器中。(用于实现SSO)
- <Host
appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false"> - //具体的context,用来指明webapp的路径
- <Context
docBase="xxx" path="/xxx" reloadable="true" source="xxx"/>
作为tomcat的启动而言,一般来说
①
②
③
3. Tomcat中请求的处理
假设来自客户的请求为:http://www.xxx.com/test/index.jsp
a.
b.
- 被唤醒线程在Engine中寻找www.xxx.com匹配的虚拟主机
- 被找到的Host获得请求/test/index.jsp,匹配它所拥有的所有Context
- Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为""的Context去处理)
- path="/test"的Context获得请求/index.jsp
- Context开始解析http请求,首先由filter处理,再次交给servlet
现行的Web框架都是由filter拦截
顺便提一下,这也就是为什么很多人说servlet不是线程安全的。
- Context把执行完了之后的HttpServletResponse对象返回给Host
- Host把HttpServletResponse对象返回给Engine
- Engine把HttpServletResponse对象返回给Connector
- Connector把HttpServletResponse对象返回给客户browser
- 线程重回wait状态