基于tomcat 5.0.28

以下是一個連接從被connector接受知道被處理所經(jīng)過的幾個步驟,其中無關(guān)代碼已省略。其中的每個方法都標(biāo)有全名,可以直接去類中查找。
[noten]代表下面的note, 如[note1],[note2].
(n) 代表第幾步,如(4) 代表第4個處理步驟 4.在CoyoteAdapter中,將connector 與 container 相關(guān)聯(lián)
$$代表作者的注釋

1. 接受一個新的連接請求
void org.apache.tomcat.util.net.TcpWorkerThread.runIt(Object[] perThrData){
       Socket s = null;
            try {
                s = endpoint.acceptSocket();
            } finally {
                // Continue accepting on another thread...
                if (endpoint.isRunning()) {
                    endpoint.tp.runIt(this);    $$此處啟動另一個TcpWorkerTread去接受其他請求,此線程處理已接受的請求
                }
            } 
                
           TcpConnection con = null;
      con = (TcpConnection) perThrData[0];
           con.setEndpoint(endpoint);
           con.setSocket(s);
           endpoint.getConnectionHandler().processConnection(con,(Object[]) perThrData[1]);     
}            

2.新接收的請求被傳到Http11ConnectionHandler中處理。

void org.apache.coyote.http11.Http11Protocol.Http11ConnectionHandler.processConnection(TcpConnection connection, Object[] thData){     
      Http11Processor  processor=null;                                                                   
            processor=(Http11Processor)thData[Http11Protocol.THREAD_DATA_PROCESSOR];   $$[note1] 為什么 thData[Http11Protocol.THREAD_DATA_PROCESSOR] 會是 Http11Processor 的一個實(shí)例.
            socket=connection.getSocket();                                                                                                     
            InputStream in = socket.getInputStream();  
            OutputStream out = socket.getOutputStream();
            processor.setSocket( socket );                                                                                                                                    
            processor.process(in, out);   $$ processor 是 org.apache.coyote.http11.Http11Processor 的 一個實(shí)例

}

3.在 Http11Processor 中處理 http11 協(xié)議相關(guān)的信息

void org.apache.coyote.http11.Http11Processor.process(InputStream input, OutputStream output) throws IOException{
        inputBuffer.setInputStream(input);
        outputBuffer.setOutputStream(output);
        inputBuffer.parseHeaders();              $$ http11 協(xié)議頭在此方法中被取出
        adapter.service(request, response);    $$ adapter 是 org.apache.coyote.tomcat5.CoyoteAdapter 的 一個實(shí)例
}

4.在CoyoteAdapter中,將connector 與 container 相關(guān)聯(lián)

void org.apache.coyote.tomcat5.CoyoteAdapter.service(Request req, Response res) throws Exception{
    
     $$ 底層使用的org.apache.coyote.Request,org.apache.coyote.Response 在此處被轉(zhuǎn)換成
     $$ org.apache.coyote.tomcat5.CoyoteRequest 和 org.apache.coyote.tomcat5.CoyoteResponse
     $$ 二者都分別實(shí)現(xiàn)了 javax.servlet.http.HttpServletRequest 和 javax.servlet.http.HttpServletResponse
    
     request = (CoyoteRequest) connector.createRequest();
         request.setCoyoteRequest(req);
         response = (CoyoteResponse) connector.createResponse();
         response.setCoyoteResponse(res);

          // Create objects
         request = (CoyoteRequest) connector.createRequest();
         request.setCoyoteRequest(req);
         response = (CoyoteResponse) connector.createResponse();
         response.setCoyoteResponse(res);

         // Link objects
         request.setResponse(response);
         response.setRequest(request);

         // Parse and set Catalina and configuration specific
         // request parameters
         if ( postParseRequest(req, request, res, response) ) {
           $$ 在 postParseRequest() 方法中, 與此request相關(guān)聯(lián)的 context 和 wrapper 對象被找出,并與此 request 關(guān)聯(lián)
           $$
           $$         // Request mapping.
          $$     connector.getMapper().map(req.serverName(), decodedURI,request.getMappingData());
          $$     request.setContext((Context) request.getMappingData().context);
          $$         request.setWrapper((Wrapper) request.getMappingData().wrapper); 
           
          
          $$$$$$$$$$$$$$$$$$$$
          $$  注意!! 此下所有的 request 和 response 對象都是 org.apache.coyote.tomcat5.CoyoteRequest 和 org.apache.coyote.tomcat5.CoyoteResponse 類的實(shí)例,
          $$ 而不是org.apache.coyote.Request,org.apache.coyote.Response 類的實(shí)例

            // Calling the container
            connector.getContainer().invoke(request, response);  $$此處connector.getContainer() 取到的是org.apache.catalina.core.StandardEngine類的實(shí)例
         } 
}

5.request 和 response 被傳送到 container 中處理

void org.apache.catalina.core.ContainerBase.invoke(Request request, Response response) throws IOException, ServletException{
        $$ 下面的 pipleline StandardPineLine 的一個實(shí)例
        $$ 在這個類的實(shí)現(xiàn)中,有這樣一行代碼
        $$ protected Pipeline pipeline = new StandardPipeline(this);
        pipeline.invoke(request, response);       
}

6.request 和 response 在 Container 的pipleline 中處理
 void org.apache.catalina.core.StandardPipeline.invoke(Request request, Response response) throws IOException, ServletException{
         StandardValveContext valveContext =
             (StandardValveContext) request.getValveContext();
         if (valveContext == null) {
             valveContext = new StandardValveContext();
             request.setValveContext(valveContext);
         }
 
         valveContext.set(basic, valves);        
         valveContext.invokeNext(request, response);
         valveContext.set(null, null); 
}

7.調(diào)用container 的 pipeline 中的 第一個valve
void org.apache.catalina.core.StandardValveContext.invokeNext(Request request, Response response) throws IOException, ServletException {
        int subscript = stage;
        stage = stage + 1;
        // Invoke the requested Valve for the current request thread
        if (subscript < valves.length) {
            valves[subscript].invoke(request, response, this);      $$ 此處只有一個basic valve, 所以此處的代碼不執(zhí)行。
        } else if ((subscript == valves.length) && (basic != null)) {
            basic.invoke(request, response, this);                  $$ 代碼執(zhí)行到此處,basic 是 org.apache.catalina.core.StandardEngineValve 類的一個實(shí)例
        } else {
            throw new ServletException
                (sm.getString("standardPipeline.noValve"));
        }
}

8.執(zhí)行 engine 的 valve
void org.apache.catalina.core.StandardEngineValve.invoke(Request request, Response response,ValveContext valveContext) throws IOException, ServletException
        // Select the Host to be used for this Request
        Host host = request.getHost();           $$[note3] host 如何得到?
        if (host == null) {
            ((HttpServletResponse) response.getResponse()).sendError
                (HttpServletResponse.SC_BAD_REQUEST,
                 sm.getString("standardEngine.noHost",
                              request.getRequest().getServerName()));
            return;
        }
        // Ask this Host to process this request
        host.getPipeline().invoke(request, response);  $$ 此處的pipleline 是 org.apache.catalina.core.StandardPipeline 類的一個實(shí)例
}

9. 調(diào)用 host 的 pipeline
void org.apache.catalina.core.StandardPipeline.invoke(Request request, Response response) throws IOException, ServletException{
         StandardValveContext valveContext =
             (StandardValveContext) request.getValveContext();
         if (valveContext == null) {
             valveContext = new StandardValveContext();
             request.setValveContext(valveContext);
         }
 
         valveContext.set(basic, valves);     
         valveContext.invokeNext(request, response);
         valveContext.set(null, null); 
}

10. 調(diào)用 host 中的 valve
void org.apache.catalina.core.StandardValveContext.invokeNext(Request request, Response response) throws IOException, ServletException {
        int subscript = stage;
        stage = stage + 1;
        // Invoke the requested Valve for the current request thread
        if (subscript < valves.length) {
            valves[subscript].invoke(request, response, this);      $$ 此處先調(diào)用一個 errorreportvalve,它是host中的valve,而且不是basic valve
        } else if ((subscript == valves.length) && (basic != null)) {
            basic.invoke(request, response, this);                  $$ 此處不執(zhí)行
        } else {
            throw new ServletException
                (sm.getString("standardPipeline.noValve"));
        }
}
11. 調(diào)用 host 的 pipeline 中的 errorreprotvalve
void org.apache.catalina.valves.ErrorReportValve.invoke(Request request, Response response,ValveContext context) throws IOException, ServletException
 context.invokeNext(request, response); $$ 此方法的第一行就調(diào)用host 中的其他valve接著處理request
 $$ 下面是錯誤處理的代碼,省略
}

12. 調(diào)用  host 的 pipeline 中的下一個valve
void org.apache.catalina.core.StandardValveContext.invokeNext(Request request, Response response) throws IOException, ServletException {
        int subscript = stage;
        stage = stage + 1;
        // Invoke the requested Valve for the current request thread
        if (subscript < valves.length) {
            valves[subscript].invoke(request, response, this);      $$ there is only two valve's in this context, one the errorreportvalve, which has been invoked in (11), so program dose not run to here
        } else if ((subscript == valves.length) && (basic != null)) {
            basic.invoke(request, response, this);                  $$ program runs here,  basic is an instance of StandardHostValve
        } else {
            throw new ServletException
                (sm.getString("standardPipeline.noValve"));
        }
}

13. 調(diào)用  host 的 pipeline 中的 StandardHostValve
void org.apache.catalina.core.StandardHostValve.invoke(Request request, Response response, ValveContext valveContext) throws IOException, ServletException{
 Context context = request.getContext();               $$ context 是 org.apache.catalina.core.StandardContext 類的一個實(shí)例
 context.getPipeline().invoke(request, response);   $$ pipeline 是 org.apache.catalina.core.StandardPipeline 類的一個實(shí)例
}

14. 調(diào)用 context 的 pipeline 中的 Valve
void org.apache.catalina.core.StandardPipeline.invoke(Request request, Response response) throws IOException, ServletException{
         StandardValveContext valveContext =
             (StandardValveContext) request.getValveContext();
         if (valveContext == null) {
             valveContext = new StandardValveContext();
             request.setValveContext(valveContext);
         }
 
         valveContext.set(basic, valves);         
         valveContext.invokeNext(request, response);
         valveContext.set(null, null); 
}

15.調(diào)用 context 的 pipeline 中的下一個 Valve
void org.apache.catalina.core.StandardValveContext.invokeNext(Request request, Response response) throws IOException, ServletException {
        int subscript = stage;
        stage = stage + 1;
        // Invoke the requested Valve for the current request thread
        if (subscript < valves.length) {
            valves[subscript].invoke(request, response, this);      $$ standcontext 的 pipeline中 只有一個basic valve, 所以此處不執(zhí)行
        } else if ((subscript == valves.length) && (basic != null)) {
            basic.invoke(request, response, this);                  $$ 程序執(zhí)行到此處, basic 是 org.apache.catalina.core.StandardContextValve 的一個實(shí)例
            throw new ServletException
                (sm.getString("standardPipeline.noValve"));
        }
}

16. 執(zhí)行 context 的 pipeline 中的 Valve
void org.apache.catalina.core.StandardContextValve.invoke(Request request, Response response, ValveContext valveContext) throws IOException, ServletException{
       HttpRequest hreq = (HttpRequest) request;
        MessageBytes requestPathMB = hreq.getRequestPathMB();
        if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))               $$從這里可知, 為什么http請求無法訪問web-inf目錄下面的內(nèi)容
            || (requestPathMB.equalsIgnoreCase("/META-INF"))
            || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
            || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
            String requestURI = hreq.getDecodedRequestURI();
            notFound(requestURI, (HttpServletResponse) response.getResponse());
            return;
        }
    
    Wrapper wrapper = request.getWrapper();          $$ wrapper從那里得到,見(4)中的注釋
    invokeInternal(wrapper, request, response);
}

17 StandardContextValve中繼續(xù)處理request 和 response
void org.apache.catalina.core.StandardContextValve.invokeInternal(Wrapper wrapper, Request request, Response response) throws IOException, ServletException{
  wrapper.getPipeline().invoke(request, response);        $$ wrapper 是 org.apache.catalina.core.StandardWrapper 類的一個實(shí)例
                              $$ pipeline 是 org.apache.catalina.core.StandardPipeline 類的一個實(shí)例
}  

18.執(zhí)行 wrapper 的 pipleline
void org.apache.catalina.core.StandardPipeline.invoke(Request request, Response response) throws IOException, ServletException{
         StandardValveContext valveContext =
             (StandardValveContext) request.getValveContext();
         if (valveContext == null) {
             valveContext = new StandardValveContext();
             request.setValveContext(valveContext);
         }
 
         valveContext.set(basic, valves);        
         valveContext.invokeNext(request, response);
         valveContext.set(null, null); 
}

19. 執(zhí)行 wrapper 的 pipeline 中的valve
void org.apache.catalina.core.StandardValveContext.invokeNext(Request request, Response response) throws IOException, ServletException {
        int subscript = stage;
        stage = stage + 1;
        // Invoke the requested Valve for the current request thread
        if (subscript < valves.length) {
            valves[subscript].invoke(request, response, this);      $$ wrapper 的 pipeline中只有一個basic valve,此處代碼不執(zhí)行
        } else if ((subscript == valves.length) && (basic != null)) {
            basic.invoke(request, response, this);                  $$ 程序執(zhí)行到此處,basic 是 org.apache.catalina.core.StandardWrapperValve 的一個實(shí)例
            throw new ServletException
                (sm.getString("standardPipeline.noValve"));
        }
}

20. 執(zhí)行 standardwrapervalve,此處將會執(zhí)行 servlet.service() 方法
void org.apache.catalina.core.StandardWrapperValve.invoke(Request request, Response response, ValveContext valveContext) throws IOException, ServletException{
   Servlet servlet = null;
   HttpServletRequest hreq = (HttpServletRequest) request.getRequest();       $$ org.apache.catalina.Request 被封裝成 javax.servlet.http.HttpServletRequest.
      HttpServletResponse hres =(HttpServletResponse) response.getResponse();   $$ org.apache.catalina.Response 被封裝成 javax.servlet.http.HttpServletResponse.
   servlet = wrapper.allocate();                     $$[note4] servlet 是如何被找到并裝載的
      if ((servlet != null) && (filterChain != null)) {
          filterChain.doFilter(hreq, hres);                               $$調(diào)用此servlet的filterchain
      }

21. 調(diào)用servlet 的 filterchain 處理 request 和 response
void org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException{
 internalDoFilter(request,response);
}

22.  調(diào)用servlet 的 filterchain 處理 request 和 response
void org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException{
 $$ 此處省略filter 處理的代碼,filter 被一個一個調(diào)用。
 
 $$ 如果http請求的是一個jsp頁面, 下面的 servlet 會是 org.apache.jasper.servlet.JspServlet 類的一個實(shí)例
 $$ 若是 html 頁面, 下面的 servlet 會是 org.apache.catalina.servlets.DefaultServlet 類的一個實(shí)例
  if ((request instanceof HttpServletRequest) &&
       (response instanceof HttpServletResponse)) { 
    servlet.service((HttpServletRequest) request, (HttpServletResponse) response);
        servlet.service(request, response);
 } else {
        servlet.service(request, response);
  }
}


$$[note1] 為什么 thData[Http11Protocol.THREAD_DATA_PROCESSOR] 會是 Http11Processor 的一個實(shí)例,是在那里被賦值的?
 下面的代碼可以說明

 Object[] org.apache.coyote.http11.Http11Protocol.Http11ConnectionHandler.init(){
     Http11Processor  processor = new Http11Processor(proto.maxHttpHeaderSize);
     thData[Http11Protocol.THREAD_DATA_PROCESSOR]=processor;
     return thData;
 }

 Object[] org.apache.tomcat.util.net.TcpWorkerThread.getInitData(){
        // no synchronization overhead, but 2 array access
        Object obj[]=new Object[2];
        obj[1]= endpoint.getConnectionHandler().init();
        obj[0]=new TcpConnection();
        return obj;
  } 
 
 void org.apache.tomcat.util.threads.ThreadPool.ControlRunnable.run(){
   Object thData[] = _toRun.getInitData();
      t.setThreadData(p, thData);
      _toRun.runIt(t.getThreadData(p));  $$此處是(1)中的 runIt(Object[] perThrData) perThrData的來歷
 }     

$$[note3] host 是如何得到了?
 Host host = request.getHost() 此處的 request 實(shí)際上是 CoyoteRequest 類的一個實(shí)例
 它是這樣實(shí)現(xiàn)的:
   public Host CoyoteRequest.getHost() {
        if (getContext() == null)
            return null;
        return (Host) getContext().getParent();  $$ 此處,host 是從與此request相關(guān)的context中得到的,
        //return ((Host) mappingData.host);      $$ 那么 context 又是如何得到的呢?見(4)中的注釋
    }
 
   
$$[note4] servlet 是如何被找到并裝載的, SingleTreadPool 模型是如何實(shí)現(xiàn)的? 
 Servlet org.apache.catalina.core.StandardWrapper.allocate() throws ServletException{
   if (singleThreadModel==false) {
       // Load and initialize our instance if necessary
        if (instance == null) {
            synchronized (this) {
                if (instance == null) {
                    try {                           
                        instance = loadServlet();
                    } catch (ServletException e) {
                        throw e;
                    } catch (Throwable e) {
                        throw new ServletException
                            (sm.getString("standardWrapper.allocate"), e);
                    }
                }
            }
        } 
       return (instance);                   $$如果servlet沒有實(shí)現(xiàn)SingleTreadModel,每次都返回同一個servlet實(shí)例
      }
     
     synchronized (instancePool) {          $$如果servlet 實(shí)現(xiàn)了SingleTreadModel, 程序執(zhí)行到此處
         while (countAllocated >= nInstances) {
             // Allocate a new instance if possible, or else wait
             if (nInstances < maxInstances) {
                     instancePool.push(loadServlet());         $$此處用一個棧來保存servlet實(shí)例
                     nInstances++;                    
             } else {                  
                     instancePool.wait();                  
             }
         }           
         countAllocated++;
         return (Servlet) instancePool.pop();
     } 
 }

 Servlet org.apache.catalina.core.StandardWrapper.loadServlet() throws ServletException{
  Servlet servlet;
  String actualClass = servletClass; $$ 對于靜態(tài)html頁面來說,此處是 org.apache.catalina.servlets.DefaultServlet
                    $$ 對于 jsp 頁面來說,此處是 org.apache.jasper.servlet.JspServlet
  Class classClass = null;                   
  classClass = classLoader.loadClass(actualClass);                   
  servlet = (Servlet) classClass.newInstance();
  servlet.init(facade);
 }

一般來講,一個簡單的catalina實(shí)現(xiàn)就是最頂層一個server, 之后是一個service,其中包括兩個結(jié)構(gòu)上并列的的組件,connctor,和engine.(connector 接受請求,engine處理請求). engine 下面是Host,   Host 下面是 Context, Context下面是Wrapper,最下面是 servlet.
一般來講,一個http request在被connector接受之后,傳到container中被處理。處理的過程簡言之就是依次調(diào)用各個catalina container的valve. 先是engine的valve,再是host, context,wrapper,然后是servlet的filter, 最后是servlet.service()