亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

How Tomcat Works(六)

系統 2019 0

本文繼續分析HttpProcessor類,該類實現了org.apache.catalina.Lifecycle接口和java.lang.Runnable接口

我們先分析它的構造函數

      
        /**
      
      
        
     * The HttpConnector with which this processor is associated.
     
      
      
        */
      
      
        private
      
       HttpConnector connector = 
      
        null
      
      
        ;


      
      
        /**
      
      
        
     * The HTTP request object we will pass to our associated container.
     
      
      
        */
      
      
        private
      
       HttpRequestImpl request = 
      
        null
      
      
        ;

    
      
      
        /**
      
      
        
     * The HTTP response object we will pass to our associated container.
     
      
      
        */
      
      
        private
      
       HttpResponseImpl response = 
      
        null
      
      
        ;

 
      
      
        /**
      
      
        
     * Construct a new HttpProcessor associated with the specified connector.
     *
     * 
      
      
        @param
      
      
         connector HttpConnector that owns this processor
     * 
      
      
        @param
      
      
         id Identifier of this HttpProcessor (unique per connector)
     
      
      
        */
      
      
        public
      
       HttpProcessor(HttpConnector connector, 
      
        int
      
      
         id) {

        
      
      
        super
      
      
        ();
        
      
      
        this
      
      .connector =
      
         connector;
        
      
      
        this
      
      .debug =
      
         connector.getDebug();
        
      
      
        this
      
      .id =
      
         id;
        
      
      
        this
      
      .proxyName =
      
         connector.getProxyName();
        
      
      
        this
      
      .proxyPort =
      
         connector.getProxyPort();
        
      
      
        this
      
      .request =
      
         (HttpRequestImpl) connector.createRequest();
        
      
      
        this
      
      .response =
      
         (HttpResponseImpl) connector.createResponse();
        
      
      
        this
      
      .serverPort =
      
         connector.getPort();
        
      
      
        this
      
      .threadName =
          "HttpProcessor[" + connector.getPort() + "][" + id + "]"
      
        ;

    }
      
    

構造函數用于初始化成員變量HttpConnector connector = null、HttpRequestImpl request = null、HttpResponseImpl response = null等

當調用它的start()方法時,用于啟動處理器線程

      
        /**
      
      
        
     * Start the background thread we will use for request processing.
     *
     * 
      
      
        @exception
      
      
         LifecycleException if a fatal startup error occurs
     
      
      
        */
      
      
        public
      
      
        void
      
       start() 
      
        throws
      
      
         LifecycleException {

        
      
      
        if
      
      
         (started)
            
      
      
        throw
      
      
        new
      
      
         LifecycleException
                (sm.getString(
      
      "httpProcessor.alreadyStarted"
      
        ));
        lifecycle.fireLifecycleEvent(START_EVENT, 
      
      
        null
      
      
        );
        started 
      
      = 
      
        true
      
      
        ;

        threadStart();

    }
      
    

調用threadStart()方法

      
        /**
      
      
        
     * Start the background processing thread.
     
      
      
        */
      
      
        private
      
      
        void
      
      
         threadStart() {

        log(sm.getString(
      
      "httpProcessor.starting"
      
        ));

        thread 
      
      = 
      
        new
      
       Thread(
      
        this
      
      
        , threadName);
        thread.setDaemon(
      
      
        true
      
      
        );
        thread.start();

        
      
      
        if
      
       (debug >= 1
      
        )
            log(
      
      " Background thread has been started"
      
        );

    }
      
    

?即啟動處理器線程,下面是run()方法

      
        /**
      
      
        
     * The background thread that listens for incoming TCP/IP connections and
     * hands them off to an appropriate processor.
     
      
      
        */
      
      
        public
      
      
        void
      
      
         run() {

        
      
      
        //
      
      
         Process requests until we receive a shutdown signal
      
      
        while
      
       (!
      
        stopped) {

            
      
      
        //
      
      
         Wait for the next socket to be assigned
      
      
            Socket socket =
      
         await();
            
      
      
        if
      
       (socket == 
      
        null
      
      
        )
                
      
      
        continue
      
      
        ;

            
      
      
        //
      
      
         Process the request from this socket
      
      
        try
      
      
         {
                process(socket);
            } 
      
      
        catch
      
      
         (Throwable t) {
                log(
      
      "process.invoke"
      
        , t);
            }

            
      
      
        //
      
      
         Finish up this request
      
      
            connector.recycle(
      
        this
      
      
        );

        }

        
      
      
        //
      
      
         Tell threadStop() we have shut ourselves down successfully
      
      
        synchronized
      
      
         (threadSync) {
            threadSync.notifyAll();
        }

    }
      
    

下面關鍵是分析await()方法與assign()方法是怎么同步的了,這里可以理解為經典的生產者與消費者模型

我們先來看assign()方法

      
        /**
      
      
        
     * Process an incoming TCP/IP connection on the specified socket.  Any
     * exception that occurs during processing must be logged and swallowed.
     * <b>NOTE</b>:  This method is called from our Connector's thread.  We
     * must assign it to our own thread so that multiple simultaneous
     * requests can be handled.
     *
     * 
      
      
        @param
      
      
         socket TCP socket to process
     
      
      
        */
      
      
        synchronized
      
      
        void
      
      
         assign(Socket socket) {

        
      
      
        //
      
      
         Wait for the Processor to get the previous Socket
      
      
        while
      
      
         (available) {
            
      
      
        try
      
      
         {
                wait();
            } 
      
      
        catch
      
      
         (InterruptedException e) {
            }
        }

        
      
      
        //
      
      
         Store the newly available Socket and notify our thread
      
      
        this
      
      .socket =
      
         socket;
        available 
      
      = 
      
        true
      
      
        ;
        notifyAll();

        
      
      
        if
      
       ((debug >= 1) && (socket != 
      
        null
      
      
        ))
            log(
      
      " An incoming request is being assigned"
      
        );

    }
      
    

成員變量默認為boolean available = false

下面是await()方法

      
        /**
      
      
        
     * Await a newly assigned Socket from our Connector, or <code>null</code>
     * if we are supposed to shut down.
     
      
      
        */
      
      
        private
      
      
        synchronized
      
      
         Socket await() {

        
      
      
        //
      
      
         Wait for the Connector to provide a new Socket
      
      
        while
      
       (!
      
        available) {
            
      
      
        try
      
      
         {
                wait();
            } 
      
      
        catch
      
      
         (InterruptedException e) {
            }
        }

        
      
      
        //
      
      
         Notify the Connector that we have received this Socket
      
      
        Socket socket = 
      
        this
      
      
        .socket;
        available 
      
      = 
      
        false
      
      
        ;
        notifyAll();

        
      
      
        if
      
       ((debug >= 1) && (socket != 
      
        null
      
      
        ))
            log(
      
      "  The incoming request has been awaited"
      
        );

        
      
      
        return
      
      
         (socket);

    }
      
    

顯然這里是采用notifyAll()方法與wait()方法相同通信,當await()方法執行notifyAll()并返回socket后,assign()方法又可以繼續接收請求socket對象了

await()方法里面采用的是局部變量,為了不占用成員變量引用(Socket socket = null),返回的socket對象供處理器線程進行處理,又要回到run()方法了

Socket socket = await()這里也是采用了局部變量,與await()方法里面采用局部變量同樣的原因

獲取socket實例后,調用process()方法進行處理,處理完畢后將處理器對象重新入棧,最后是如果收到停止處理器線程命令,則事件通知可以停止線程了

下面關鍵是process()方法,這個方法有點長

      
        /**
      
      
        
     * Process an incoming HTTP request on the Socket that has been assigned
     * to this Processor.  Any exceptions that occur during processing must be
     * swallowed and dealt with.
     *
     * 
      
      
        @param
      
      
         socket The socket on which we are connected to the client
     
      
      
        */
      
      
        private
      
      
        void
      
      
         process(Socket socket) {
        
      
      
        boolean
      
       ok = 
      
        true
      
      
        ;
        
      
      
        boolean
      
       finishResponse = 
      
        true
      
      
        ;
        SocketInputStream input 
      
      = 
      
        null
      
      
        ;
        OutputStream output 
      
      = 
      
        null
      
      
        ;

        
      
      
        //
      
      
         Construct and initialize the objects we will need
      
      
        try
      
      
         {
            input 
      
      = 
      
        new
      
      
         SocketInputStream(socket.getInputStream(),
                                          connector.getBufferSize());
        } 
      
      
        catch
      
      
         (Exception e) {
            log(
      
      "process.create"
      
        , e);
            ok 
      
      = 
      
        false
      
      
        ;
        }

        keepAlive 
      
      = 
      
        true
      
      
        ;

        
      
      
        while
      
       (!stopped && ok &&
      
         keepAlive) {

            finishResponse 
      
      = 
      
        true
      
      
        ;

            
      
      
        try
      
      
         {
                request.setStream(input);
                request.setResponse(response);
                output 
      
      =
      
         socket.getOutputStream();
                response.setStream(output);
                response.setRequest(request);
                ((HttpServletResponse) response.getResponse()).setHeader
                    (
      
      "Server"
      
        , SERVER_INFO);
            } 
      
      
        catch
      
      
         (Exception e) {
                log(
      
      "process.create"
      
        , e);
                ok 
      
      = 
      
        false
      
      
        ;
            }


            
      
      
        //
      
      
         Parse the incoming request
      
      
        try
      
      
         {
                
      
      
        if
      
      
         (ok) {

                    parseConnection(socket);
                    parseRequest(input, output);
                    
      
      
        if
      
       (!
      
        request.getRequest().getProtocol()
                        .startsWith(
      
      "HTTP/0"
      
        ))
                        parseHeaders(input);
                    
      
      
        if
      
      
         (http11) {
                        
      
      
        //
      
      
         Sending a request acknowledge back to the client if
                        
      
      
        //
      
      
         requested.
      
      
                                ackRequest(output);
                        
      
      
        //
      
      
         If the protocol is HTTP/1.1, chunking is allowed.
      
      
        if
      
      
         (connector.isChunkingAllowed())
                            response.setAllowChunking(
      
      
        true
      
      
        );
                    }

                }
            } 
      
      
        catch
      
      
         (EOFException e) {
                
      
      
        //
      
      
         It's very likely to be a socket disconnect on either the
                
      
      
        //
      
      
         client or the server
      
      
                ok = 
      
        false
      
      
        ;
                finishResponse 
      
      = 
      
        false
      
      
        ;
            } 
      
      
        catch
      
      
         (ServletException e) {
                ok 
      
      = 
      
        false
      
      
        ;
                
      
      
        try
      
      
         {
                    ((HttpServletResponse) response.getResponse())
                        .sendError(HttpServletResponse.SC_BAD_REQUEST);
                } 
      
      
        catch
      
      
         (Exception f) {
                    ;
                }
            } 
      
      
        catch
      
      
         (InterruptedIOException e) {
                
      
      
        if
      
       (debug > 1
      
        ) {
                    
      
      
        try
      
      
         {
                        log(
      
      "process.parse"
      
        , e);
                        ((HttpServletResponse) response.getResponse())
                            .sendError(HttpServletResponse.SC_BAD_REQUEST);
                    } 
      
      
        catch
      
      
         (Exception f) {
                        ;
                    }
                }
                ok 
      
      = 
      
        false
      
      
        ;
            } 
      
      
        catch
      
      
         (Exception e) {
                
      
      
        try
      
      
         {
                    log(
      
      "process.parse"
      
        , e);
                    ((HttpServletResponse) response.getResponse()).sendError
                        (HttpServletResponse.SC_BAD_REQUEST);
                } 
      
      
        catch
      
      
         (Exception f) {
                    ;
                }
                ok 
      
      = 
      
        false
      
      
        ;
            }

            
      
      
        //
      
      
         Ask our Container to process this request
      
      
        try
      
      
         {
                ((HttpServletResponse) response).setHeader
                    (
      
      "Date"
      
        , FastHttpDateFormat.getCurrentDate());
                
      
      
        if
      
      
         (ok) {
                    connector.getContainer().invoke(request, response);
                }
            } 
      
      
        catch
      
      
         (ServletException e) {
                log(
      
      "process.invoke"
      
        , e);
                
      
      
        try
      
      
         {
                    ((HttpServletResponse) response.getResponse()).sendError
                        (HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                } 
      
      
        catch
      
      
         (Exception f) {
                    ;
                }
                ok 
      
      = 
      
        false
      
      
        ;
            } 
      
      
        catch
      
      
         (InterruptedIOException e) {
                ok 
      
      = 
      
        false
      
      
        ;
            } 
      
      
        catch
      
      
         (Throwable e) {
                log(
      
      "process.invoke"
      
        , e);
                
      
      
        try
      
      
         {
                    ((HttpServletResponse) response.getResponse()).sendError
                        (HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                } 
      
      
        catch
      
      
         (Exception f) {
                    ;
                }
                ok 
      
      = 
      
        false
      
      
        ;
            }

            
      
      
        //
      
      
         Finish up the handling of the request
      
      
        if
      
      
         (finishResponse) {
                
      
      
        try
      
      
         {
                    response.finishResponse();
                } 
      
      
        catch
      
      
         (IOException e) {
                    ok 
      
      = 
      
        false
      
      
        ;
                } 
      
      
        catch
      
      
         (Throwable e) {
                    log(
      
      "process.invoke"
      
        , e);
                    ok 
      
      = 
      
        false
      
      
        ;
                }
                
      
      
        try
      
      
         {
                    request.finishRequest();
                } 
      
      
        catch
      
      
         (IOException e) {
                    ok 
      
      = 
      
        false
      
      
        ;
                } 
      
      
        catch
      
      
         (Throwable e) {
                    log(
      
      "process.invoke"
      
        , e);
                    ok 
      
      = 
      
        false
      
      
        ;
                }
                
      
      
        try
      
      
         {
                    
      
      
        if
      
       (output != 
      
        null
      
      
        )
                        output.flush();
                } 
      
      
        catch
      
      
         (IOException e) {
                    ok 
      
      = 
      
        false
      
      
        ;
                }
            }

            
      
      
        //
      
      
         We have to check if the connection closure has been requested
            
      
      
        //
      
      
         by the application or the response stream (in case of HTTP/1.0
            
      
      
        //
      
      
         and keep-alive).
      
      
        if
      
       ( "close".equals(response.getHeader("Connection"
      
        )) ) {
                keepAlive 
      
      = 
      
        false
      
      
        ;
            }

            
      
      
        //
      
      
         End of request processing
      
      
            status =
      
         Constants.PROCESSOR_IDLE;

            
      
      
        //
      
      
         Recycling the request and the response objects
      
      
                    request.recycle();
            response.recycle();

        }

        
      
      
        try
      
      
         {
            shutdownInput(input);
            socket.close();
        } 
      
      
        catch
      
      
         (IOException e) {
            ;
        } 
      
      
        catch
      
      
         (Throwable e) {
            log(
      
      "process.invoke"
      
        , e);
        }
        socket 
      
      = 
      
        null
      
      
        ;

    }
      
    

上面方法中,首先根據參數socket的輸入流與輸出流初始化request對象與response對象,接著是解析輸入流并填充request對象和 response對象 ,接下來調用容器對象的void invoke(Request request, Response response)方法具體進行處理

接下來清理并回收request對象和response對象

注:keepAlive表示是否是持久連接

最后是檢查輸入流是否有未讀完的字節并跳過這些字節和關閉socket實例。

下面是一個簡單的容器,實現了org.apache.catalina.Container接口,關鍵代碼如下

      
        public
      
      
        class
      
       SimpleContainer 
      
        implements
      
      
         Container {

  
      
      
        public
      
      
        static
      
      
        final
      
       String WEB_ROOT =
      
        
    System.getProperty(
      
      "user.dir") + File.separator  + "webroot"
      
        ;

  
      
      
        public
      
      
         SimpleContainer() {
  } 
      
      
        public
      
      
         Loader getLoader() {
    
      
      
        return
      
      
        null
      
      
        ;
  }

  
      
      
        public
      
      
        void
      
      
         setLoader(Loader loader) {
  } 
      
      
        public
      
      
        void
      
      
         invoke(Request request, Response response)
    
      
      
        throws
      
      
         IOException, ServletException {

    String servletName 
      
      =
      
         ( (HttpServletRequest) request).getRequestURI();
    servletName 
      
      = servletName.substring(servletName.lastIndexOf("/") + 1
      
        );
    URLClassLoader loader 
      
      = 
      
        null
      
      
        ;
    
      
      
        try
      
      
         {
      URL[] urls 
      
      = 
      
        new
      
       URL[1
      
        ];
      URLStreamHandler streamHandler 
      
      = 
      
        null
      
      
        ;
      File classPath 
      
      = 
      
        new
      
      
         File(WEB_ROOT);
      String repository 
      
      = (
      
        new
      
       URL("file", 
      
        null
      
      , classPath.getCanonicalPath() +
      
         File.separator)).toString() ;
      urls[
      
      0] = 
      
        new
      
       URL(
      
        null
      
      
        , repository, streamHandler);
      loader 
      
      = 
      
        new
      
      
         URLClassLoader(urls);
    }
    
      
      
        catch
      
      
         (IOException e) {
      System.out.println(e.toString() );
    }
    Class myClass 
      
      = 
      
        null
      
      
        ;
    
      
      
        try
      
      
         {
      myClass 
      
      =
      
         loader.loadClass(servletName);
    }
    
      
      
        catch
      
      
         (ClassNotFoundException e) {
      System.out.println(e.toString());
    }

    Servlet servlet 
      
      = 
      
        null
      
      
        ;

    
      
      
        try
      
      
         {
      servlet 
      
      =
      
         (Servlet) myClass.newInstance();
      servlet.service((HttpServletRequest) request, (HttpServletResponse) response);
    }
    
      
      
        catch
      
      
         (Exception e) {
      System.out.println(e.toString());
    }
    
      
      
        catch
      
      
         (Throwable e) {
      System.out.println(e.toString());
    }

  }  

}
      
    

該方法與前面文章的ServletProcessor類的process()方法類似,不再具體分析

---------------------------------------------------------------------------?

本系列How Tomcat Works系本人原創?

轉載請注明出處 博客園 刺猬的溫馴?

本人郵箱: chenying998179 # 163.com ( #改為@

本文鏈接 http://www.cnblogs.com/chenying99/p/3235534.html

How Tomcat Works(六)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美国一级毛片片aa | 国产亚洲精品资源一区 | 九九热视频免费在线观看 | 午夜精品久久久久久久99热浪潮 | 乱人伦99久久| 亚洲精品成人7777在线观看 | 四虎www| 99免费精品| 久久久久一级片 | 亚洲成人7777 | 日本一级看片免费播放 | 欧洲成人免费高清视频 | 亚洲日本一区二区三区在线不卡 | 亚洲男人的天堂在线视频 | a级高清观看视频在线看 | 日本在线视频精品 | 日日摸夜夜添夜夜添影院视频 | 操操操干干干 | 人人狠狠综合久久亚洲88 | 亚洲第一区第二区 | 日韩欧美国产高清 | 99九九精品国产高清自在线 | 一区二区三区国产精品 | 久久精品国产这里是免费 | 精品在线一区二区 | 波多野结衣视频一区 | h片免费网站 | 国产在线观看91精品一区 | 96精品国产高清在线看入口 | 一级毛片免费视频观看 | 成人激情小视频 | 国产手机精品一区二区 | 国产精品高清视亚洲一区二区 | 一区二区三区欧美日韩国产 | 亚洲精品自产拍在线观看 | 精品一区二区三区在线观看视频 | 亚洲一区二区在线 | 在线欧美v日韩v国产精品v | 亚洲第一人黄所 | 欧美四虎影院 | 欧美精品日日鲁夜夜 |