Tomcat學習之Wrapper

來源:互聯網
上載者:User

標籤:

 Tomcat學習之Wrapper分類: WEB伺服器2012-08-30 22:16 1547人閱讀 評論(0) 收藏 舉報tomcatservletwrapperservletslistexception

Wrapper 代表一個 Servlet,它負責管理一個 Servlet,包括的 Servlet 的裝載、初始化、執行以及資源回收。它的父容器一般是Context,Wrapper 是最底層的容器,它沒有子容器了,所以調用它的 addChild 將會拋illegalargumentexception。Wrapper 的實作類別是 StandardWrapper,StandardWrapper 還實現了擁有一個 Servlet 初始化資訊的 ServletConfig,由此看出 StandardWrapper 將直接和 Servlet 的各種資訊打交道。

在StandardContext啟動時,讀取web.xml設定檔,配置Context之後,緊接著啟動Context的一些附屬組件,除此以外還載入了那些標記為"load on start"的那些wrapper

[java] view plaincopyprint? 
  1. // Load and initialize all "load on startup" servlets  
  2. if (ok) {  
  3.     loadOnStartup(findChildren());  
  4. }  
[java] view plaincopyprint? 
  1. public void loadOnStartup(Container children[]) {  
  2.   
  3.        // Collect "load on startup" servlets that need to be initialized  
  4.        TreeMap<Integer, ArrayList<Wrapper>> map =  
  5.            new TreeMap<Integer, ArrayList<Wrapper>>();  
  6.        for (int i = 0; i < children.length; i++) {  
  7.            Wrapper wrapper = (Wrapper) children[i];  
  8.            int loadOnStartup = wrapper.getLoadOnStartup();  
  9.            if (loadOnStartup < 0)  
  10.                continue;  
  11.            Integer key = Integer.valueOf(loadOnStartup);  
  12.            ArrayList<Wrapper> list = map.get(key);  
  13.            if (list == null) {  
  14.                list = new ArrayList<Wrapper>();  
  15.                map.put(key, list);  
  16.            }  
  17.            list.add(wrapper);  
  18.        }  
  19.   
  20.        // Load the collected "load on startup" servlets  
  21.        for (ArrayList<Wrapper> list : map.values()) {  
  22.            for (Wrapper wrapper : list) {  
  23.                try {  
  24.                    wrapper.load();  
  25.                } catch (ServletException e) {  
  26.                    getLogger().error(sm.getString("standardWrapper.loadException",  
  27.                                      getName()), StandardWrapper.getRootCause(e));  
  28.                    // NOTE: load errors (including a servlet that throws  
  29.                    // UnavailableException from tht init() method) are NOT  
  30.                    // fatal to application startup  
  31.                }  
  32.            }  
  33.        }  
  34.   
  35.    }  

這個方法做了兩件事:

1、遍曆這些wrapper,將其放入一個map中。key為啟動順序,value是同一啟動順序的servlet list,為了保護數字小的先啟動,這裡用了treemap這種資料結構來儲存;

2、遍曆這個map,依次載入對應list中的各個wrapper。由於採用的是arrayList,所以相同"load on start"值靠前的先載入

下面來看看StandardWrapper的load方法,直接調用了loadServlet方法來初始化 [java] view plaincopyprint? 
  1. public synchronized void load() throws ServletException {  
  2.        instance = loadServlet();  
  3.          
  4.        if (!instanceInitialized) {  
  5.            initServlet(instance);  
  6.        }  
  7.   
  8.        if (isJspServlet) {  
  9.            StringBuilder oname =  
  10.                new StringBuilder(MBeanUtils.getDomain(getParent()));  
  11.              
  12.            oname.append(":type=JspMonitor,name=");  
  13.            oname.append(getName());  
  14.              
  15.            oname.append(getWebModuleKeyProperties());  
  16.              
  17.            try {  
  18.                jspMonitorON = new ObjectName(oname.toString());  
  19.                Registry.getRegistry(null, null)  
  20.                    .registerComponent(instance, jspMonitorON, null);  
  21.            } catch( Exception ex ) {  
  22.                log.info("Error registering JSP monitoring with jmx " +  
  23.                         instance);  
  24.            }  
  25.        }  
  26.    }  
[java] view plaincopyprint? 
  1.  private synchronized void initServlet(Servlet servlet)throws ServletException {  
  2.      if (instanceInitialized && !singleThreadModel) return;  
  3.      // Call the initialization method of this servlet  
  4.      try {  
  5.         instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT, servlet);  
  6. if (Globals.IS_SECURITY_ENABLED) {  
  7.     Object[] args = new Object[] { (facade) };  
  8.     SecurityUtil.doAsPrivilege("init", servlet, classType, args);  
  9.     args = null;  
  10. } else {  
  11.     servlet.init(facade);  
  12. }  
  13.   
  14. instanceInitialized = true;  
  15. instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet);  
  16.      } catch (UnavailableException f) {  
  17. //handle exception  
  18.      }  
  19.  }  
實際上是調用了servlet的init方法,這已經是servlet的代碼了,這裡不再分析。

前面提到的servlet的載入只是被標識為“load on start”的那些servlet,那麼其他servlet是在什麼時候被載入的呢?選中StandardWrapper的initServlet方法,在eclipse中查看其調用層次如下:

會發現有個allocate方法間接調用了它,這裡給出請求進入wrapper之後的方法調用時序圖:

可以看出在請求進入wrapper之後,通過allocate方法從執行個體池棧中彈出一個servlet執行個體來處理這個請求,servlet執行個體被封裝成filterChain對象,緊接著通過一系列的過濾器過濾到達servlet.service()方法,這是singleThreadModel模式的做法。在非singleThreadModel模式的情況下首次載入並初始始化servlet賦給instance欄位,下次直接從這個欄位中擷取servlet執行個體,因此在非singleThreadModel模式下每次返回的是同一個servlet執行個體。有關singleThreadModel的具體介紹參考:http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/SingleThreadModel.html

Tomcat學習之Wrapper

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.