tomcat源码分析学习笔记(四)

——每天的寥寥几笔,坚持下去,将会是一份沉甸甸的积累。


今天的笔记是针对《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容器就放在下一篇文章吧




你可能感兴趣的:(tomcat,源码,servlet,管道,servlet容器,阀)