管道组件 - 969251639/study GitHub Wiki
管道跟流一样,可有由多个管道拼接而成,而管道的每个拼接点叫阀门,在tomcat中叫Base,Base需要调用下一个管道的First,所有管道最后组成一条单向链表。它可以用来将tomcat的多个内部组件流转起来,然后到每个组件的尽头都会有一个阀门去连接下一段管道
注:tomcat管道的开头都是first,结尾都是base
管道的起点是当tomcat连接请求时在工作线程池里会调用SocketProccess的run方法,run方法中会从Connector组件开始,逐步流向内部组件
public class CoyoteAdapter implements Adapter {
...
@SuppressWarnings("deprecation")
@Override
public void service(org.apache.coyote.Request req,
org.apache.coyote.Response res)
throws Exception {
...
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
...
}
...
}
找到最顶的的pipeline,也就是service中的container,也就是Engine,标准实现类是StandardEngine
public class StandardEngine extends ContainerBase implements Engine {
...
public StandardEngine() {
super();
pipeline.setBasic(new StandardEngineValve());
/* Set the jmvRoute using the system property jvmRoute */
try {
setJvmRoute(System.getProperty("jvmRoute"));
} catch(Exception ex) {
log.warn(sm.getString("standardEngine.jvmRouteFail"));
}
// By default, the engine will hold the reloading thread
backgroundProcessorDelay = 10;
}
...
}
初始化时设置了管道的阀门StandardEngineValve
其中管道的创建都是在它的父类ContainerBase中创建
public abstract class ContainerBase extends LifecycleMBeanBase
implements Container {
...
protected final Pipeline pipeline = new StandardPipeline(this);
...
}
接下来看StandardEngineValve的invoke方法
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Select the Host to be used for this Request
Host host = request.getHost();
if (host == null) {
response.sendError
(HttpServletResponse.SC_BAD_REQUEST,
sm.getString("standardEngine.noHost",
request.getServerName()));
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(host.getPipeline().isAsyncSupported());
}
// Ask this Host to process this request
host.getPipeline().getFirst().invoke(request, response);
}
基本上不做什么操作,就是将request和response交给下一个管道处理(也就是host组件),接下来的几个组件都是类似,不断的通过管道留给下一个组件
从上图可以看到tomcat的管道流向:
engine -> host -> context -> wrapper
其实我们也可以自定管道,然后插入到上面的任何一个点中,比如tomcat自带的一个请求日志
在上面的host节点中,配置了一个valve,valve就是tomcat可以在管道处理的一个节点,我们也可以自定义自己的一个valve,插入到想要流入的节点上,只要继承ValveBase类即可,然后重写invoke方法实现自己的逻辑,最后在server.xml配上自己的管道