淺讀tomcat架構設計之Pipeline-Valve管道(4)

  tomcat Container容器處理請求是使用Pipeline-Valve管道來處理的,後續寫的tomcat內存馬,和他緊密結合

  Pipeline-Valve是責任鏈模式,責任鏈模式是指在一個請求處理的過程有多個處理者依次對請求進行處理,每個處理者負責做自己相應的處理,處理完成後將處理後的請求返回,再讓下一個處理者繼續處理. 簡單點來說就是Pipeline就是請求,發起各種請求, Valve用於處理過來的所有請求,你的請求都會走Valve,進行處理檢查.

  (1)每個Pipeline都有特定的Valve,而且是在管道的最後一個執行,Valve的接口實現類是ValveBase

  (2)在上層容器的管道的ValveBase會調用下層容器的管道

  ValveBase的子類,有很多,分別有這些:

   我着重講下這四個子類

  其中要講的是這四個類,他們和Context,Engine,Host和Wrapper的請求處理息息相關.

  Pipeline-Valve的實現方法:

  Pipeline的接口實現類是org.apache.catalina.core.StandardPipeline:

    StandardPipeline繼承自LifecycleBase,所以StandardPipeline是生命週期類

  查看startInternal方法:

    

  protected synchronized void startInternal() throws LifecycleException {
        Valve current = this.first;
        if (current == null) {
            current = this.basic;
        }

        for(; current != null; current = current.getNext()) {
            if (current instanceof Lifecycle) {
                ((Lifecycle)current).start();
            }
        }

        this.setState(LifecycleState.STARTING);
    }

  

  學過數據結構的話,會感到很熟悉,我博客文章之前寫過類似的代碼,他是個鏈式結構,遍歷所有的Valve並調用start方法,最後設置狀態.

   stopInternal和destroyInternal方法如下:

  protected synchronized void stopInternal() throws LifecycleException {
        this.setState(LifecycleState.STOPPING);
        Valve current = this.first;
        if (current == null) {
            current = this.basic;
        }

        for(; current != null; current = current.getNext()) {
            if (current instanceof Lifecycle) {
                ((Lifecycle)current).stop();
            }
        }

    }

    protected void destroyInternal() {
        Valve[] valves = this.getValves();
        Valve[] arr$ = valves;
        int len$ = valves.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            Valve valve = arr$[i$];
            this.removeValve(valve);
        }

    }

  代碼和startInternal相似,都是使用current臨時變量遍歷Valve的所有Valve,destoryInternal是刪除所有的valve

  

  Pipeline管道處理請求的實現方法:

  Engine,先從ValveBase的子類StandEngineValve類開始org.apache.catalina.core.StandardEngineValve

    Pipeline管道調用所包含Valve的invoke來處理請求,invoke方法來處理請求

    invoke方法:

    

  public final void invoke(Request request, Response response) throws IOException, ServletException {
        Host host = request.getHost();
        if (host == null) {
            response.sendError(400, sm.getString("standardEngine.noHost", new Object[]{request.getServerName()}));
        } else {
            if (request.isAsyncSupported()) {
                request.setAsyncSupported(host.getPipeline().isAsyncSupported());
            }

            host.getPipeline().getFirst().invoke(request, response);
        }
    }

 

 

 

  首先通過reuquest獲取Host站點,然後調用管道的第一個Valve的invoke方法進行處理

  

  Host,org.apache.catalina.core.StandardHostValve#invoke方法:    

 

  代碼太長,截取部分,Host的ValveBase調用的是Context的Pipeline

  Context,org.apache.catalina.core.StandardContextValve#invoke方法:

    

 

   代碼太長,截取部分,Context的ValveBase調用的是Wrapper的Pipeline

  Wrapper,org.apache.catalina.core.StandardWrapperValve#invoke方法:

    

 

 

      

 

 

    代碼太長,截取部分,Wrapper是封裝Servlet的,ValveBase內部調用的是filterChain來處理請求的

  Filter和Servlet的實際處理請求的方法在Wrapper的管道Pipeline->Valve-ValveBase-StandardWrapperValve#invoke方法中調用,Wrapper生命週期是在org.apache.catalina.core.StandardWrapper中調用,因爲StandardWrapper繼承自ContainerBase,ContainerBase又繼承自LifecycleMBeanBase  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章