——每天的寥寥几笔,坚持下去,将会是一份沉甸甸的积累。
今天的笔记是针对《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容器就放在下一篇文章吧。