Tomcat之请求在容器内执行源码分析
请求在容器内的调用
![](https://img.haomeiwen.com/i7310356/9f5050d753652c3d.png)
StandardEngine、StandardHost、StandardContext、StandardWrapper是容器的层级结构,以父子关系存在。
都继承了ContainerBase类,容器抽象类。包含parent、child、pipeline、realm等属性。pipeline中会设置Valve阀门,在请求流经容器执行时,会通过默认阀门传递到子容器对象。默认阀门StandardEngineValve、StandardHostValve、StandardContextValve、StandardWrapperValve。调用一层层阀门,在StandardWrapperValve类中会执行过滤链和自定义Servlet实现。
容器调用执行点
1、getService()
从连接对象connector获取StandardService对象
![](https://img.haomeiwen.com/i7310356/47fb0e54e237bf92.png)
2、getContainer()
从service获取engine对象StandardEngine
![](https://img.haomeiwen.com/i7310356/1eb6ac79d4c555c3.png)
3、getPipeline
从engine对象获取pipline
![](https://img.haomeiwen.com/i7310356/d1e2feef05157015.png)
invoke方法
1、调用engine的阀门value的invoke方法
org.apache.catalina.core.StandardEngineValve#invoke
![](https://img.haomeiwen.com/i7310356/134a8af76776b6d3.png)
先获取请求的Host的实现类,之后调用Host的阀门value的invoke方法
![](https://img.haomeiwen.com/i7310356/3d3c96d85dfeedea.png)
其中StandardHost的孩子容器有6个,其中包含我们部署的testservlet项目。这六个就是webapps目录下的6个文件夹
![](https://img.haomeiwen.com/i7310356/cf8a2a33c11e70c4.png)
2、调用Host的阀门value的invoke方法
StandardHost的pipeline有三个,其中first是AbstractAccessLogValve
![](https://img.haomeiwen.com/i7310356/5cb472b15d57aac8.png)
①、先调用AbstractAccessLogValve的invoke方法
org.apache.catalina.valves.AbstractAccessLogValve#invoke
![](https://img.haomeiwen.com/i7310356/75ad2ec1ff98af25.png)
②、ErrorReportValve
org.apache.catalina.valves.ErrorReportValve#invoke
![](https://img.haomeiwen.com/i7310356/eb9de6074f4ba4de.png)
③、StandardHostValve
org.apache.catalina.core.StandardHostValve#invoke
![](https://img.haomeiwen.com/i7310356/067d651f879325ce.png)
3、调用Context的阀门value的invoke方法
首先获取Context对象
![](https://img.haomeiwen.com/i7310356/7dc36a97cccb8edd.png)
org.apache.catalina.core.ContainerBase#getPipeline
![](https://img.haomeiwen.com/i7310356/d261f91916e28fdf.png)
org.apache.catalina.core.StandardPipeline#getFirst
![](https://img.haomeiwen.com/i7310356/6288c726c37ced3d.png)
①、AuthenticatorBase
org.apache.catalina.authenticator.AuthenticatorBase#invoke
进行身份验证
![](https://img.haomeiwen.com/i7310356/ea729d0665e1c356.png)
![](https://img.haomeiwen.com/i7310356/592760187ea4744c.png)
realm得到的为null,jaspicProvider为null。调用下一个value的invoke方法
![](https://img.haomeiwen.com/i7310356/23a002a423ad67cb.png)
②、StandardContextValve
org.apache.catalina.core.StandardContextValve#invoke
包含META-INF则返回错误
![](https://img.haomeiwen.com/i7310356/13dbbade8a2ddafd.png)
获取当前请求Wrapper
![](https://img.haomeiwen.com/i7310356/75ca3f005e6113c9.png)
发送确认、设置异步支持、继续调用invoke
![](https://img.haomeiwen.com/i7310356/0b8be27391121a6a.png)
4、调用Wrapper的阀门value的invoke方法
org.apache.catalina.core.StandardWrapperValve#invoke
①、初始化一些参数值,并获取wrap的父容器context
![](https://img.haomeiwen.com/i7310356/bc4b5aedb050a3e1.png)
②、检查当前应用的context和servlet是否被标记为无效
![](https://img.haomeiwen.com/i7310356/81222c2d0337d423.png)
③、为请求分配servlet对象
![](https://img.haomeiwen.com/i7310356/fb1ac90eb4750054.png)
allocate
org.apache.catalina.core.StandardWrapper#allocate
根据singleThreadModel是否是单线程模式分配,不是单线程则会每次相同请求都会分配一个对象
![](https://img.haomeiwen.com/i7310356/c4e6e572ccf08d46.png)
![](https://img.haomeiwen.com/i7310356/899f0e8fc4e6caf9.png)
loadServlet
org.apache.catalina.core.StandardWrapper#loadServlet
![](https://img.haomeiwen.com/i7310356/3129a8b912e9f7f9.png)
newInstance
org.apache.catalina.core.DefaultInstanceManager#newInstance(java.lang.String)
根据类构造方法创建对象
![](https://img.haomeiwen.com/i7310356/4d67f1864e2a86df.png)
如果singleThreadModel=true单线程模型,那么将会从instancePool池中获取
![](https://img.haomeiwen.com/i7310356/fbb68e0b4fc15e17.png)
④、获取过滤链filterChain
设置请求request属性,并获取过滤链filterChain,我们自定义的过滤器对象就会在这里获取到
![](https://img.haomeiwen.com/i7310356/d2fcf5980ebe0fa3.png)
⑤、过滤链doFilter执行
![](https://img.haomeiwen.com/i7310356/cb9de42c1fd98147.png)
org.apache.catalina.core.ApplicationFilterChain#doFilter
![](https://img.haomeiwen.com/i7310356/8038966c757d9281.png)
org.apache.catalina.core.ApplicationFilterChain#internalDoFilter
这里是根据执行链的位置pos与包含数量n来判断执行
![](https://img.haomeiwen.com/i7310356/347a943d423523be.png)
这里如果包含过滤链将会调用doFilter方法
![](https://img.haomeiwen.com/i7310356/5019d098af93c0a3.png)
⑥、在链的末尾调用servlet实例方法
![](https://img.haomeiwen.com/i7310356/608c51116ecb0913.png)
调用到自定义对象HelloServlet实例方法
Globals.IS_SECURITY_ENABLED=false
![](https://img.haomeiwen.com/i7310356/6e41e14ec6ca1f29.png)
这里会根据servlet协议实现类javax.servlet.http.HttpServlet#service调用
总结:
请求在容器内的调用核心就是通过Value阀门的不同容器级别不同实现类的invoke来传递调用的。
不同容器包含的默认实现Value阀门类。
在容器内的调用过程最后才调用到过滤链和自定义的servlet实现