黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

How Tomcat Works(七)

系統(tǒng) 2270 0

本文接下來(lái)介紹并分析servlet容器,servlet容器是用來(lái)處理請(qǐng)求servlet資源,并為web客戶端填充response對(duì)象的模塊。

servlet容器是org.apache.catalina.Container接口的實(shí)例,在tomcat中,有四種類型的容器,分別為Engine、Host 、Context和Wrapper。

Engine. 代表整個(gè)容器的servlet引擎。
Host.代表一個(gè)擁有一定數(shù)量Context的虛擬主機(jī)。
Context.代表一個(gè)Web項(xiàng)目.一個(gè)Context包含一個(gè)或多個(gè)Wrapper。
Wrapper.代表單獨(dú)的一個(gè)servlet。

這些容器構(gòu)成一個(gè)自頂向下的等級(jí)結(jié)構(gòu),高等級(jí)的容器可以具有多個(gè)直接下屬等級(jí)的容器實(shí)例(子容器),這有點(diǎn)類似于composite模式,不過(guò)還是有差別的

org.apache.catalina.Container接口聲明如下

      
        //
      
      
        添加
      
      
        public
      
      
        void
      
      
         addChild(Container child);

      
      
        //
      
      
        刪除
      
      
        public
      
      
        void
      
      
         removeChild(Container child);

      
      
        //
      
      
        查找
      
      
        public
      
      
         Container findChild(String name);

      
      
        //
      
      
        查找全部
      
      
        public
      
       Container[] findChildren();
    

上面方法均為操作子容器的相關(guān)方法

容器可以包含一些支持的組件,諸如載入器、記錄器、管理器、領(lǐng)域和資源等,我們可以通過(guò)編輯server.xml文件來(lái)決定使用哪種容器。

下面我們來(lái)分析servlet容器是怎么執(zhí)行任務(wù)的,這里就要提到servlet容器的管道模型,管道包含了該servlet容器將要調(diào)用的任務(wù),而閥則表示一個(gè)具體的執(zhí)行任務(wù);在servlet容器的管道中,有一個(gè)基礎(chǔ)閥,也可以添加任意數(shù)量的額外閥,閥的數(shù)量通常是指額外添加的閥的數(shù)量,不包括基礎(chǔ)閥

這里就好像servlet編程中的過(guò)濾器模型,管道好比過(guò)濾器鏈,而閥則是具體的過(guò)濾器;基礎(chǔ)閥總是最后一個(gè)執(zhí)行的。

這里涉及幾個(gè)相關(guān)的接口,包括Pipeline、Valve、ValveContext 和Contained

Pipeline接口聲明如下

      
        public
      
      
        interface
      
      
         Pipeline {
   
      
      
        public
      
      
         Valve getBasic();

      
      
        public
      
      
        void
      
      
         setBasic(Valve valve);
    
      
      
        public
      
      
        void
      
      
         addValve(Valve valve);
   
      
      
        public
      
      
         Valve[] getValves();
   
      
      
        public
      
      
        void
      
      
         invoke(Request request, Response response)
        
      
      
        throws
      
      
         IOException, ServletException;
   
      
      
        public
      
      
        void
      
      
         removeValve(Valve valve);

}
      
    

Valve接口聲明如下

      
        public
      
      
        interface
      
      
         Valve {
        
public String getInfo(); public void invoke(Request request, Response response, ValveContext context) throws IOException, ServletException; }

ValveContext接口聲明

      
        public
      
      
        interface
      
      
         ValveContext {
  
      
      
        public
      
      
         String getInfo();
   
      
      
        public
      
      
        void
      
      
         invokeNext(Request request, Response response)
        
      
      
        throws
      
      
         IOException, ServletException;
}
      
    

Contained接口聲明

      
        public
      
      
        interface
      
      
         Contained {
    
      
      
        public
      
      
         Container getContainer();
   
      
      
        public
      
      
        void
      
      
         setContainer(Container container);

}
      
    

閥可以選擇是否實(shí)現(xiàn)該接口,設(shè)置閥與一個(gè)servlet容器相關(guān)連

下面我們來(lái)學(xué)習(xí)Wrapper容器,Wrapper容器表示一個(gè)獨(dú)立的servlet定義,負(fù)責(zé)管理其基礎(chǔ)servlet類的生命周期,它繼承了Container接口,另外添加了額外方法聲明。其中比較重要的方法聲明是load()方法和allocate()方法,均與載入及初始化servlet類相關(guān)(供基礎(chǔ)閥調(diào)用,基礎(chǔ)閥持有Wrapper容器實(shí)例引用)

下面來(lái)分析一個(gè)簡(jiǎn)單的Wrapper類,該類實(shí)現(xiàn)了org.apache.catalina.Wrapper接口和org.apache.catalina.Pipeline接口

      
        public
      
      
        class
      
       SimpleWrapper 
      
        implements
      
      
         Wrapper, Pipeline {

  
      
      
        //
      
      
         the servlet instance
      
      
        private
      
       Servlet instance = 
      
        null
      
      
        ;
  
      
      
        private
      
      
         String servletClass;
  
      
      
        private
      
      
         Loader loader; 
      
      
        private
      
       SimplePipeline pipeline = 
      
        new
      
       SimplePipeline(
      
        this
      
      
        );
  
      
      
        protected
      
       Container parent = 
      
        null
      
      
        ;

  
      
      
        public
      
      
         SimpleWrapper() {
    pipeline.setBasic(
      
      
        new
      
      
         SimpleWrapperValve());
  }

  
      
      
        public
      
      
        synchronized
      
      
        void
      
      
         addValve(Valve valve) {
    pipeline.addValve(valve);
  }

  
      
      
        public
      
       Servlet allocate() 
      
        throws
      
      
         ServletException {
    
      
      
        //
      
      
         Load and initialize our instance if necessary
      
      
        if
      
       (instance==
      
        null
      
      
        ) {
      
      
      
        try
      
      
         {
        instance 
      
      =
      
         loadServlet();
      }
      
      
      
        catch
      
      
         (ServletException e) {
        
      
      
        throw
      
      
         e;
      }
      
      
      
        catch
      
      
         (Throwable e) {
        
      
      
        throw
      
      
        new
      
       ServletException("Cannot allocate a servlet instance"
      
        , e);
      }
    }
    
      
      
        return
      
      
         instance;
  }

  
      
      
        private
      
       Servlet loadServlet() 
      
        throws
      
      
         ServletException {
    
      
      
        if
      
       (instance!=
      
        null
      
      
        )
      
      
      
        return
      
      
         instance;

    Servlet servlet 
      
      = 
      
        null
      
      
        ;
    String actualClass 
      
      =
      
         servletClass;
    
      
      
        if
      
       (actualClass == 
      
        null
      
      
        ) {
      
      
      
        throw
      
      
        new
      
       ServletException("servlet class has not been specified"
      
        );
    }

    Loader loader 
      
      =
      
         getLoader();
    
      
      
        //
      
      
         Acquire an instance of the class loader to be used
      
      
        if
      
       (loader==
      
        null
      
      
        ) {
      
      
      
        throw
      
      
        new
      
       ServletException("No loader."
      
        );
    }
    ClassLoader classLoader 
      
      =
      
         loader.getClassLoader();

    
      
      
        //
      
      
         Load the specified servlet class from the appropriate class loader
      
      
    Class classClass = 
      
        null
      
      
        ;
    
      
      
        try
      
      
         {
      
      
      
        if
      
       (classLoader!=
      
        null
      
      
        ) {
        classClass 
      
      =
      
         classLoader.loadClass(actualClass);
      }
    }
    
      
      
        catch
      
      
         (ClassNotFoundException e) {
      
      
      
        throw
      
      
        new
      
       ServletException("Servlet class not found"
      
        );
    }
    
      
      
        //
      
      
         Instantiate and initialize an instance of the servlet class itself
      
      
        try
      
      
         {
      servlet 
      
      =
      
         (Servlet) classClass.newInstance();
    }
    
      
      
        catch
      
      
         (Throwable e) {
      
      
      
        throw
      
      
        new
      
       ServletException("Failed to instantiate servlet"
      
        );
    }

    
      
      
        //
      
      
         Call the initialization method of this servlet
      
      
        try
      
      
         {
      servlet.init(
      
      
        null
      
      
        );
    }
    
      
      
        catch
      
      
         (Throwable f) {
      
      
      
        throw
      
      
        new
      
       ServletException("Failed initialize servlet."
      
        );
    }
    
      
      
        return
      
      
         servlet;
  }  
      
      
        public
      
      
         Loader getLoader() {
    
      
      
        if
      
       (loader != 
      
        null
      
      
        )
      
      
      
        return
      
      
         (loader);
    
      
      
        if
      
       (parent != 
      
        null
      
      
        )
      
      
      
        return
      
      
         (parent.getLoader());
    
      
      
        return
      
       (
      
        null
      
      
        );
  }
      
      
        public
      
      
        void
      
      
         invoke(Request request, Response response)
    
      
      
        throws
      
      
         IOException, ServletException {
    pipeline.invoke(request, response);
  }  
      
      
        public
      
      
        void
      
       load() 
      
        throws
      
      
         ServletException {
    instance 
      
      =
      
         loadServlet();
  }
        
// method implementations of Pipeline public Valve getBasic() { return pipeline.getBasic(); } public void setBasic(Valve valve) { pipeline.setBasic(valve); } public Valve[] getValves() { return pipeline.getValves(); } public void removeValve(Valve valve) { pipeline.removeValve(valve); } }

上面的SimpleWrapper類由于實(shí)現(xiàn)了org.apache.catalina.Pipeline接口接口,同時(shí)與該接口相關(guān)的實(shí)現(xiàn)方法都是調(diào)用引用的成員變量SimplePipeline pipeline = new SimplePipeline(this)的對(duì)應(yīng)方法,因此我們可以理解為SimpleWrapper類為SimplePipeline的包裝類

在它的invoke()方法里面調(diào)用了成員變量的SimplePipeline pipeline = new SimplePipeline(this)的invoke()方法,這里構(gòu)造函數(shù)傳入SimpleWrapper實(shí)例本身,可以猜想是為了獲取其載入器及具體的servlet實(shí)現(xiàn)類(注:該方法為Container接口與Pipeline接口都具有的方法聲明,因此SimpleWrapper類只要一個(gè)實(shí)現(xiàn)),下面我們繼續(xù)分析SimplePipeline相關(guān)實(shí)現(xiàn)

      
        public
      
      
        class
      
       SimplePipeline 
      
        implements
      
      
         Pipeline {

  
      
      
        public
      
      
         SimplePipeline(Container container) {
    setContainer(container);
  }

  
      
      
        //
      
      
         The basic Valve (if any) associated with this Pipeline.
      
      
        protected
      
       Valve basic = 
      
        null
      
      
        ;
  
      
      
        //
      
      
         The Container with which this Pipeline is associated.
      
      
        protected
      
       Container container = 
      
        null
      
      
        ;
  
      
      
        //
      
      
         the array of Valves
      
      
        protected
      
       Valve valves[] = 
      
        new
      
       Valve[0
      
        ];

  
      
      
        public
      
      
        void
      
      
         setContainer(Container container) {
    
      
      
        this
      
      .container =
      
         container;
  }

  
      
      
        public
      
      
         Valve getBasic() {
    
      
      
        return
      
      
         basic;
  }

  
      
      
        public
      
      
        void
      
      
         setBasic(Valve valve) {
    
      
      
        this
      
      .basic =
      
         valve;
    ((Contained) valve).setContainer(container);
  }

  
      
      
        public
      
      
        void
      
      
         addValve(Valve valve) {
    
      
      
        if
      
       (valve 
      
        instanceof
      
      
         Contained)
      ((Contained) valve).setContainer(
      
      
        this
      
      
        .container);

    
      
      
        synchronized
      
      
         (valves) {
      Valve results[] 
      
      = 
      
        new
      
       Valve[valves.length +1
      
        ];
      System.arraycopy(valves, 
      
      0, results, 0
      
        , valves.length);
      results[valves.length] 
      
      =
      
         valve;
      valves 
      
      =
      
         results;
    }
  }

  
      
      
        public
      
      
         Valve[] getValves() {
    
      
      
        return
      
      
         valves;
  }

  
      
      
        public
      
      
        void
      
      
         invoke(Request request, Response response)
    
      
      
        throws
      
      
         IOException, ServletException {
    
      
      
        //
      
      
         Invoke the first Valve in this pipeline for this request
      
      
    (
      
        new
      
      
         SimplePipelineValveContext()).invokeNext(request, response);
  }

  
      
      
        public
      
      
        void
      
      
         removeValve(Valve valve) {
  }

  
      
      
        //
      
      
         this class is copied from org.apache.catalina.core.StandardPipeline class's
  
      
      
        //
      
      
         StandardPipelineValveContext inner class.
      
      
        protected
      
      
        class
      
       SimplePipelineValveContext 
      
        implements
      
      
         ValveContext {

    
      
      
        protected
      
      
        int
      
       stage = 0
      
        ;

    
      
      
        public
      
      
         String getInfo() {
      
      
      
        return
      
      
        null
      
      
        ;
    }

    
      
      
        public
      
      
        void
      
      
         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
      
      
        );
      }
      
      
      
        else
      
      
        if
      
       ((subscript == valves.length) && (basic != 
      
        null
      
      
        )) {
        basic.invoke(request, response, 
      
      
        this
      
      
        );
      }
      
      
      
        else
      
      
         {
        
      
      
        throw
      
      
        new
      
       ServletException("No valve"
      
        );
      }
    }
  } 
      
      
        //
      
      
         end of inner class
      
      
        
}
      
    

invoke()方法里面調(diào)用內(nèi)部類SimplePipelineValveContext(實(shí)現(xiàn)了ValveContext接口),遍歷執(zhí)行各個(gè)閥的invoke()方法

wrapper容器執(zhí)行的基本流程如上所述,下面我們來(lái)進(jìn)一步分析相關(guān)輔助類及實(shí)現(xiàn)類等

在應(yīng)用初始化servlet容器時(shí),我們需要為其指定一個(gè)載入器,下面是一個(gè)簡(jiǎn)單的載入器,實(shí)現(xiàn)了Loader接口

      
        public
      
      
        class
      
       SimpleLoader 
      
        implements
      
      
         Loader {

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

  ClassLoader classLoader 
      
      = 
      
        null
      
      
        ;
  Container container 
      
      = 
      
        null
      
      
        ;

  
      
      
        public
      
      
         SimpleLoader() {
    
      
      
        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);
      classLoader 
      
      = 
      
        new
      
      
         URLClassLoader(urls);
    }
    
      
      
        catch
      
      
         (IOException e) {
      System.out.println(e.toString() );
    }


  }

  
      
      
        public
      
      
         ClassLoader getClassLoader() {
    
      
      
        return
      
      
         classLoader;
  }

  
      
      
        public
      
      
         Container getContainer() {
    
      
      
        return
      
      
         container;
  }
   
      
      
        //
      
      
        這里省略其余代碼
      
      
}
    

基礎(chǔ)閥是干嘛的呢,具體來(lái)說(shuō)是調(diào)用具體servlet的service()方法(管道持有對(duì)基礎(chǔ)閥的引用)

      
        public
      
      
        class
      
       SimpleWrapperValve 
      
        implements
      
      
         Valve, Contained {

  
      
      
        protected
      
      
         Container container;

  
      
      
        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) {
    }
  }

  
      
      
        public
      
      
         String getInfo() {
    
      
      
        return
      
      
        null
      
      
        ;
  }

  
      
      
        public
      
      
         Container getContainer() {
    
      
      
        return
      
      
         container;
  }

  
      
      
        public
      
      
        void
      
      
         setContainer(Container container) {
    
      
      
        this
      
      .container =
      
         container;
  }
}
      
    

其他額外添加的閥本人就不在具體描述了,至此SimpleWrapper容器分析完畢!

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

本系列How Tomcat Works系本人原創(chuàng)?

轉(zhuǎn)載請(qǐng)注明出處 博客園 刺猬的溫馴?

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

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

How Tomcat Works(七)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

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

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論