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容器就放在下一篇文章吧



發佈了52 篇原創文章 · 獲贊 9 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章