主要是《深入剖析tomcat》的第五章和第十一章。个人觉得如下3点是关键:
1. pipeline相关概念及其执行valve的顺序;
2. standardwrapper的接受http请求时候的调用序列;
3. standardwrapper基础阀加载servlet的过程(涉及到STM);
顺便问一句,应该每一个servlet程序员都知道filter。但是你知道Filter在tomcat的哪一个地方出现的吗?答案是standardwrapper基础阀会创建Filter链,并调用doFilter()方法
servlet容器的作用
管理servlet资源,并为web客户端填充response对象。
不同级别的容器
Engine:表示整个Catalina的servlet引擎、
Host:表示一个拥有数个上下文的虚拟主机
Context:表示一个Web应用,一个context包含一个或多个wrapper
Wrapper:表示一个独立的servlet
容器都实现了Container接口,继承了ContainerBase抽象类。
管道任务
3个概念:pipeline、valve、valveContext
pipeline包含servlet容器将要调用的任务集合,定义如下:
public interface Pipeline {
public Valve getBasic();
public void setBasic(Valve valve);
public void addValve(Valve valve);
public Valve[] getValves();
public void invoke(Request request, Response response) throws IOException, ServletException;
public void removeValve(Valve valve);
}
valve表示一个具体的执行任务,定义如下:
public interface Valve {
public String getInfo();
public void invoke(Request request, Response response, ValveContext context) throws IOException, ServletException;
}
valveContext按照字面意思就是阀门的上下文,用于遍历valve
public interface ValveContex{
public String getInfo();
public void invokeNext(Request request, Response response) throws IOException, ServletException;
}
valveContext的invokeNext()方法的实现:
public final void invokeNext(Request request, Response response) throws IOException, ServletException {
int subscript = stage; stage = stage + 1;
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 (sm.getString("standardPipeline.noValve"));
}
}
一个阀门的invoke方法可以如下实现:
public void invoke(Request request, Response response, ValveContext valveContext) throws IOException, ServletException {
//Pass the request and response on to the next valve in our pipeline
valveContext.invokeNext(request, response);
// now perform what this valve is supposed to do ...
}
如果pipeline由valve1、valve2、valve3组成,调用valve1. Invoke()会发生什么?执行顺序是什么样的?假设valveN(N=1,2,3)的invoke()方法实现如下:
valveContext.invokeNext(request, response);
System.out.println(“valve1 invoke!”);
如果注意到了invokeNext()的实现,这层调用类似与下面的图: