基于tomcat 5.0.28

以下是一个连接从被connector接受知道被处理所经过的几个步骤,其中无关代码已省略。其中的每个方法都标有全名,可以直接去类中查找。
[noten]代表下面的note, 如[note1],[note2].
(n) 代表第几步,如(4) 代表第4个处理步骤 4.在CoyoteAdapter中,将connector 与 container 相关联
$$代表作者的注释

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 的一个实例.
            socket=connection.getSocket();                                                                                                     
            InputStream in = socket.getInputStream();  
            OutputStream out = socket.getOutputStream();
            processor.setSocket( socket );                                                                                                                                    
            processor.process(in, out);   $$ processor 是 org.apache.coyote.http11.Http11Processor 的 一个实例

}

3.在 Http11Processor 中处理 http11 协议相关的信息

void org.apache.coyote.http11.Http11Processor.process(InputStream input, OutputStream output) throws IOException{
        inputBuffer.setInputStream(input);
        outputBuffer.setOutputStream(output);
        inputBuffer.parseHeaders();              $$ http11 协议头在此方法中被取出
        adapter.service(request, response);    $$ adapter 是 org.apache.coyote.tomcat5.CoyoteAdapter 的 一个实例
}

4.在CoyoteAdapter中,将connector 与 container 相关联

void org.apache.coyote.tomcat5.CoyoteAdapter.service(Request req, Response res) throws Exception{
    
     $$ 底层使用的org.apache.coyote.Request,org.apache.coyote.Response 在此处被转换成
     $$ org.apache.coyote.tomcat5.CoyoteRequest 和 org.apache.coyote.tomcat5.CoyoteResponse
     $$ 二者都分别实现了 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相关联的 context 和 wrapper 对象被找出,并与此 request 关联
           $$
           $$         // 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 类的实例,
          $$ 而不是org.apache.coyote.Request,org.apache.coyote.Response 类的实例

            // Calling the container
            connector.getContainer().invoke(request, response);  $$此处connector.getContainer() 取到的是org.apache.catalina.core.StandardEngine类的实例
         } 
}

5.request 和 response 被传送到 container 中处理

void org.apache.catalina.core.ContainerBase.invoke(Request request, Response response) throws IOException, ServletException{
        $$ 下面的 pipleline StandardPineLine 的一个实例
        $$ 在这个类的实现中,有这样一行代码
        $$ 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.调用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, 所以此处的代码不执行。
        } else if ((subscript == valves.length) && (basic != null)) {
            basic.invoke(request, response, this);                  $$ 代码执行到此处,basic 是 org.apache.catalina.core.StandardEngineValve 类的一个实例
        } else {
            throw new ServletException
                (sm.getString("standardPipeline.noValve"));
        }
}

8.执行 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 类的一个实例
}

9. 调用 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. 调用 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);      $$ 此处先调用一个 errorreportvalve,它是host中的valve,而且不是basic valve
        } else if ((subscript == valves.length) && (basic != null)) {
            basic.invoke(request, response, this);                  $$ 此处不执行
        } else {
            throw new ServletException
                (sm.getString("standardPipeline.noValve"));
        }
}
11. 调用 host 的 pipeline 中的 errorreprotvalve
void org.apache.catalina.valves.ErrorReportValve.invoke(Request request, Response response,ValveContext context) throws IOException, ServletException
 context.invokeNext(request, response); $$ 此方法的第一行就调用host 中的其他valve接着处理request
 $$ 下面是错误处理的代码,省略
}

12. 调用  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. 调用  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 类的一个实例
 context.getPipeline().invoke(request, response);   $$ pipeline 是 org.apache.catalina.core.StandardPipeline 类的一个实例
}

14. 调用 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.调用 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, 所以此处不执行
        } else if ((subscript == valves.length) && (basic != null)) {
            basic.invoke(request, response, this);                  $$ 程序执行到此处, basic 是 org.apache.catalina.core.StandardContextValve 的一个实例
            throw new ServletException
                (sm.getString("standardPipeline.noValve"));
        }
}

16. 执行 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目录下面的内容
            || (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中继续处理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 类的一个实例
                              $$ pipeline 是 org.apache.catalina.core.StandardPipeline 类的一个实例
}  

18.执行 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. 执行 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,此处代码不执行
        } else if ((subscript == valves.length) && (basic != null)) {
            basic.invoke(request, response, this);                  $$ 程序执行到此处,basic 是 org.apache.catalina.core.StandardWrapperValve 的一个实例
            throw new ServletException
                (sm.getString("standardPipeline.noValve"));
        }
}

20. 执行 standardwrapervalve,此处将会执行 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);                               $$调用此servlet的filterchain
      }

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

22.  调用servlet 的 filterchain 处理 request 和 response
void org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException{
 $$ 此处省略filter 处理的代码,filter 被一个一个调用。
 
 $$ 如果http请求的是一个jsp页面, 下面的 servlet 会是 org.apache.jasper.servlet.JspServlet 类的一个实例
 $$ 若是 html 页面, 下面的 servlet 会是 org.apache.catalina.servlets.DefaultServlet 类的一个实例
  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 的一个实例,是在那里被赋值的?
 下面的代码可以说明

 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 实际上是 CoyoteRequest 类的一个实例
 它是这样实现的:
   public Host CoyoteRequest.getHost() {
        if (getContext() == null)
            return null;
        return (Host) getContext().getParent();  $$ 此处,host 是从与此request相关的context中得到的,
        //return ((Host) mappingData.host);      $$ 那么 context 又是如何得到的呢?见(4)中的注释
    }
 
   
$$[note4] servlet 是如何被找到并装载的, SingleTreadPool 模型是如何实现的? 
 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没有实现SingleTreadModel,每次都返回同一个servlet实例
      }
     
     synchronized (instancePool) {          $$如果servlet 实现了SingleTreadModel, 程序执行到此处
         while (countAllocated >= nInstances) {
             // Allocate a new instance if possible, or else wait
             if (nInstances < maxInstances) {
                     instancePool.push(loadServlet());         $$此处用一个栈来保存servlet实例
                     nInstances++;                    
             } else {                  
                     instancePool.wait();                  
             }
         }           
         countAllocated++;
         return (Servlet) instancePool.pop();
     } 
 }

 Servlet org.apache.catalina.core.StandardWrapper.loadServlet() throws ServletException{
  Servlet servlet;
  String actualClass = servletClass; $$ 对于静态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实现就是最顶层一个server, 之后是一个service,其中包括两个结构上并列的的组件,connctor,和engine.(connector 接受请求,engine处理请求). engine 下面是Host,   Host 下面是 Context, Context下面是Wrapper,最下面是 servlet.
一般来讲,一个http request在被connector接受之后,传到container中被处理。处理的过程简言之就是依次调用各个catalina container的valve. 先是engine的valve,再是host, context,wrapper,然后是servlet的filter, 最后是servlet.service()