——每天的寥寥几笔,坚持下去,将会是一份沉甸甸的积累。
今天的笔记是针对《how tomcat works》的第五章——servlet容器。。
该书的【源码及书籍下载链接:http://pan.baidu.com/s/1ntBhXX3】
1.概念:一个连接httpConnector和serlvet的中间体,负责处理客户请求、把请求传送给Servlet并把结果返回给客户。说白了,你把httpConnector那里得到的request和response交给容器,容器能够帮你找到对应的servlet,并把servlet的处理结果放到response中。
2.servlet容器有四种,engine、host、context、wrapper,从大到小,前者可以包含一个或多个后者。其中wrapper为最小单位(不能再小了),只能负责一个servlet。
3.对于一个wrapper,有如下结构:
- 一个管道pipeline //类似一个过滤链
- 一个管道含有一个基阀和多个普通阀//一个基阀是必须有的,普通阀看情况添加。每个阀类似一个过滤器。
-----------------------------------------------------------
-simplePipeline 管道类
-SimpleWrapper servlet容器
-SimpleWrapperVavle基阀
-HeaderLoggerVavle普通阀
4.程序流程:
bootstrap类初始化,并启动HTTPconnector;
httpConnector触发servlet容器的invoke方法
HttpConnector connector = new HttpConnector();//新建连接器
Wrapper wrapper = new SimpleWrapper();
Valve valve1 = new HeaderLoggerValve();//新建普通阀
((Pipeline) wrapper).addValve(valve1);//容器添加普通阀,实际上是容器内管道添加阀。wrapper.addVavle()代码:pipeline.addValve(valve);
connector.setContainer(wrapper);//这和tomcat分析二中一样,设置容器,关联连接器和servlet容器
connector.initialize();
connector.start();
基阀的初始化是在容器构造器中实现的
public SimpleWrapper() {
pipeline.setBasic(new SimpleWrapperValve());
}
->wrapper调用invoke方法
wrapper类:public void invoke(Request request, Response response)
throws IOException, ServletException {
pipeline.invoke(request, response);
}
->pipeline调用invoke方法
pipeline类:public void invoke(Request request, Response response)
throws IOException, ServletException {
(new SimplePipelineValveContext()).invokeNext(request, response);
}
->pipeline的内部类SimplePipelineValveContext调用invokeNext方法
public 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);//阀又调用invoke方法
}
else if ((subscript == valves.length) && (basic != null)) {
basic.invoke(request, response, this);
}
else {
throw new ServletException("No valve");
}
}
从invoke到invokeNext又到invoke再到invokeNext,不断把每个阀都遍历到,最后调用基阀的invoke方法。
->调用基阀的invoke方法结束。
public void invoke(Request request, Response response, ValveContext valveContext)
throws IOException, ServletException {
SimpleWrapper wrapper = (SimpleWrapper) getContainer();
ServletRequest sreq = request.getRequest();
ServletResponse sres = response.getResponse();
Servlet servlet = null;
HttpServletRequest hreq = null;
if (sreq instanceof HttpServletRequest)
hreq = (HttpServletRequest) sreq;
HttpServletResponse hres = null;
if (sres instanceof HttpServletResponse)
hres = (HttpServletResponse) sres;
// Allocate a servlet instance to process this request
try {
servlet = wrapper.allocate();//*****************//
if (hres!=null && hreq!=null) {
servlet.service(hreq, hres);
}
else {
servlet.service(sreq, sres);
}
}
catch (ServletException e) {
}
}
--------------------------------------------------------------------end.
注意:不过上面还有一个地方值得说一下,最后一个invoke(也就是基阀的invoke)中//***//标注的那一句
servlet = wrapper.allocate();
servlet的实例化是在wrapper类的allocate方法中进行的。
servlet = (Servlet) classClass.newInstance();
servlet.init(null);//这里可以进行相关init的处理
内容挺多,context容器就放在下一篇文章吧。