Pipeline
首先看下pipeline是什么
Tomcat中的容器是有层级结构的,每层容器关注点不同
当请求到来时,会将请求交给最上层的容器,当上层容器处理完之后,会交给下层容器
每层容器都有一个Pipeline对象,Piple中包含了多个Valve,每个Valve代表了对请求的处理逻辑
并且每层容器的Pipeline中都会有一个Basic Valve,这个Valve总是在该层Pipeline中最后一个执行,在该Valve中会将请求交给子容器的Pipeline,从而将不同层次的容器的执行处理逻辑连接起来
下面先看下Pipeline和Valve是怎么执行的
Pipeline
这里主要看下实现类StandardPipeline,该实现类不仅实现了Pipeline接口,并且实现了Lifecycle接口,因此也具有生命周期
startInternal
这个类的initInternal为空,因此我们主要看下startInternal
protected synchronized void startInternal() throws LifecycleException {
// Start the Valves in our pipeline (including the basic), if any
Valve current = first;
if (current == null) {
current = basic;
}
while (current != null) {
if (current instanceof Lifecycle)
((Lifecycle) current).start();
current = current.getNext();
}
setState(LifecycleState.STARTING);
}
这个方法主要是遍历所有的valve,然后分别启动这些valve
addValve
通过addValve方法来向pipeline中添加valve
并且维护valve的前后关系,并且永远确保base valve是最后一个valve
public void addValve(Valve valve) {
// Validate that we can add this Valve
if (valve instanceof Contained)
((Contained) valve).setContainer(this.container);
// Start the new component if necessary
if (getState().isAvailable()) {
if (valve instanceof Lifecycle) {
try {
((Lifecycle) valve).start();
} catch (LifecycleException e) {
log.error(sm.getString("standardPipeline.valve.start"), e);
}
}
}
// Add this Valve to the set associated with this Pipeline
if (first == null) {
first = valve;
valve.setNext(basic);
} else {
Valve current = first;
while (current != null) {
if (current.getNext() == basic) {
current.setNext(valve);
valve.setNext(basic);
break;
}
current = current.getNext();
}
}
container.fireContainerEvent(Container.ADD_VALVE_EVENT, valve);
}
Valve
这里看下StandardContextValve做了哪些操作,是如何将请求传递到子容器的
可以看到在通过请求获取到请求对应的wrapper之后,会调用wrapper的pipeline中第一个valve,从而将当前的处理逻辑和子容器的处理逻辑串起来
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Disallow any direct access to resources under WEB-INF or META-INF
MessageBytes requestPathMB = request.getRequestPathMB();
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
// Select the Wrapper to be used for this Request
Wrapper wrapper = request.getWrapper();
if (wrapper == null || wrapper.isUnavailable()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
// Acknowledge the request
try {
response.sendAcknowledgement(ContinueResponseTiming.IMMEDIATELY);
} catch (IOException ioe) {
container.getLogger().error(sm.getString(
"standardContextValve.acknowledgeException"), ioe);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
}
wrapper.getPipeline().getFirst().invoke(request, response);
}