容器是一个处理用户servlet请求并返回对象给web用户的模块。org.apache.catalina.Container接口定义了容器的形式,有四种容器:Engine(引擎), Host(主机), Context(上下文), 和 Wrapper(包装器)。Engine:表示整个Catalina的servlet引擎 · Host:表示一个拥有数个上下文的虚拟主机 · Context:表示一个Web应用,一个context包含一个或多个wrapper · Wrapper:表示一个独立的servlet。一个容器可以有一个或多个低层次上的子容器。例如,一个Context有一个或多个wrapper,而wrapper作为容器层次中的最底层,不能包含子容器。容器包含addchild(),findchild等用来添加寻找子容器的方法接口。
下面我们来介绍容器调用invoke方法之后的具体实现,这里主要在于关注wrapper和context的具体实现。
下面还是通过代码来进行分析,看wrapper的invoke方法:
public void invoke(Request request, Response response)
throws IOException, ServletException {
pipeline.invoke(request, response);
}
这里调用了pipeline的invoke方法,pipeline即流水线的设计模式,流水线模式是一种很直观的设计模式,下面我们来看pipeline接口的定义, 它包含getBasic(),setBasic(), addValve, removeValve, 以及invoke方法,valve即阀门,可以想象成一道又一道的关卡,需要过了上一个才能进行下一关,这里的basic就是最后一道关卡。另外,如果是在并行计算的设计中,通关的时间将由最耗时的那一关来决定。
下面我们来看pipeline的invoke方法,一个实现了pipeline接口的类的invoke方法如下:
public void invoke(Request request, Response response)
throws IOException, ServletException {
// Invoke the first Valve in this pipeline for this request
(new StandardPipelineValveContext()).invokeNext(request, response);
}
<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
下面是 StandardPipelineValveContext():
protected class StandardPipelineValveContext implements ValveContext {
protected int stage = 0;
public String getInfo() {
return null;
}
public void invokeNext(Request request, Response response)
throws IOException, ServletException {
int subscript = stage;
stage = stage + 1;
// Invoke the requested Valve for the current request thread
if (subscript < valves.length) {
valves[subscript].invoke(request, response, this);
}
else if ((subscript == valves.length) && (basic != null)) {
basic.invoke(request, response, this);
}
else {
throw new ServletException("No valve");
}
}
} // end of inner class
}
流水线通过创建一个ValveContext接口的实例来实现它。ValveContext是流水线的的内部类,这样ValveContext就可以访问流水线中所有的成员。ValveContext中最重要的方法是invokeNext方法,subscript是当前valve的下标,通过它来一步步的进行下一步的valve。
未完,待续