Jetty源碼學習3-啓動服務器

引言 java

本文主要介紹下環境準備、啓動加載的配置文件的涵義和start.jar的加載原理。 web

環境準備 shell

一、下載jetty-distribution-8.1.7.v20120910源碼包並加入eclipse工程classpath中 api

二、準備一個war工程 app

三、拷貝到jetty的webapp目錄 eclipse

四、jetty源碼打斷點,並在jetty的start.jar目錄下執行: java -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8090 -DEOS_DEBUG=true -jar start.jar,注意端口號。 webapp

五、要研究初始化能夠在server的doStart斷點,研究一次請求過程能夠在server的handler斷點。 socket

配置文件 ide

一、start.ini this

指導jetty啓動時須要加載的配置文件與順序。

#etc/jetty-jmx.xml
etc/jetty.xml
etc/jetty-annotations.xml
# etc/jetty-ssl.xml
# etc/jetty-requestlog.xml
etc/jetty-deploy.xml
#etc/jetty-overlay.xml
etc/jetty-webapps.xml
etc/jetty-contexts.xml
etc/jetty-testrealm.xml

這些配置文件的順序不能錯,好比如果將jetty-deploy.xml置於最下面將致使jetty-webapps沒法初始化的錯誤。簡單介紹下幾個配置的做用:

1)jmx.xml

去掉該註釋,容器中的某些類便能在運行時受管理;好比:若是工程須要在不重啓的狀況下從新讀取某配置文件,能夠經過信號量的方式或者jmx的方式。這由於該功能管理着工程中須要被管理的類,所以置於最上方。

2)jetty.xml

這個就不解釋了,該配製文件就對應了server類,管理着connection,thread pool,handler等。

3)deploy.xml

該配置文件對應於上篇博客描述的deployService,在jetty中就是deployManager,部署管理器,所以若是這玩意位置錯了,下面的webapps.xml天然就報錯了。

4)webapps.xml

war包的部署器,webappcontext便於基於今生產出來的。

5)contexts.xml

另外一種部署器,主要是讀取部署目錄下的xml文件,不知道用在哪裏,先略過。

二、jetty.xml

<Configure id="Server" class="org.eclipse.jetty.server.Server">

    <!-- =========================================================== -->
    <!-- Server Thread Pool                                          -->
    <!-- =========================================================== -->
    <Set name="ThreadPool">
      <!-- Default queued blocking threadpool -->
      <New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
        <Set name="minThreads">10</Set>
        <Set name="maxThreads">200</Set>
        <Set name="detailedDump">false</Set>
      </New>
    </Set>

    <!-- =========================================================== -->
    <!-- Set connectors                                              -->
    <!-- =========================================================== -->

    <Call name="addConnector">
      <Arg>
          <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
            <Set name="host"><Property name="jetty.host" /></Set>
            <Set name="port"><Property name="jetty.port" default="8888"/></Set>
            <Set name="maxIdleTime">300000</Set>
            <Set name="Acceptors">2</Set>
            <Set name="statsOn">false</Set>
            <Set name="confidentialPort">8443</Set>
	    <Set name="lowResourcesConnections">20000</Set>
	    <Set name="lowResourcesMaxIdleTime">5000</Set>
          </New>
      </Arg>
    </Call>

    <!-- =========================================================== -->
    <!-- Set handler Collection Structure                            --> 
    <!-- =========================================================== -->
    <Set name="handler">
      <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
        <Set name="handlers">
         <Array type="org.eclipse.jetty.server.Handler">
           <Item>
             <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
           </Item>
           <Item>
             <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>
           </Item>
         </Array>
        </Set>
      </New>
    </Set>
</Configure>

能夠看出默認的io爲nio,hanler是server中比較核心的方法,Contexts是一個webappcontext的集合,請求進來的時候Contexts負責將請求分發給具體的app;而DefaultHandler即返回404錯誤頁面,其實從這個handlers就能夠看出來,請求會一次通過這個handler,一旦被hanlder即提交退出,直到不被handler走到了DefaultHandler裏面返回404的頁面。這裏面其實自定義handler加載handlers的頭部處理一些靜態資源的訪問,這樣就直接繞過了應用webappcontext的訪問了,加快了靜態資源的處理速度。eg:RerourceHandler.

三、deploy.xml

<Configure id="Server" class="org.eclipse.jetty.server.Server">

    <Call name="addBean">
      <Arg>
        <New id="DeploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager">
          <Set name="contexts">
            <Ref id="Contexts" />
          </Set>
          <Call name="setContextAttribute">
            <Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg>
            <Arg>.*/servlet-api-[^/]*\.jar$</Arg>
          </Call>
        </New>
      </Arg>
    </Call>
</Configure>

調用addBean方法,Ref  = contexts 即上面server中已經new出來的 ContextHandlerCollection,持有該contexts旨在註冊全部由該類生產出來的一個個app(即WebAppContextHandler)

四、webapps.xml

<Configure id="Server" class="org.eclipse.jetty.server.Server">
    <Ref id="DeploymentManager">
          <Call id="webappprovider" name="addAppProvider">
            <Arg>
              <New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
                <Set name="monitoredDirName"><Property name="jetty.home" default="." />/webapps</Set>
                <Set name="defaultsDescriptor"><Property name="jetty.home" default="."/>/etc/webdefault.xml</Set>
                <Set name="scanInterval">1</Set>
                <Set name="contextXmlDir"><Property name="jetty.home" default="." />/contexts</Set>
		<Set name="extractWars">true</Set>
              </New>
            </Arg>
          </Call>
    </Ref>
</Configure>

war工程的部署器,人如其名:WebAppProvider。從下面配的參數不難看出其主要功能,它主要是負責掃描目錄下的war工程並生產ContextHandler(其實就是servletContext,對應於一個個app),而WebAppProvider又是受上面deployManager管理,生產出來的ContextHandler被deployManager註冊到ContextHandlerCollection中。

start.jar加載原理

一、解析命令行參數

List arguments = new ArrayList();  
for (String arg1 : args)  
{  
  if ((arg1.startsWith("--ini=")) || (arg1.equals("--ini")))  
  {  
      arguments.addAll(loadStartIni(arg1.substring(6)));  
  }  
  else if (arg1.startsWith("--config="))  
  {  
    this._startConfig = arg1.substring(9);  
  }  
  else  
  {  
    arguments.add(arg1);  
  }  
}  
if (!(ini)){ arguments.addAll(0, loadStartIni(null));}

先是解析命令行的參數,最後將ini配置文件merge起來。

二、定位加載資源並依據配置文件反射調用相應的類

// For all arguments, load properties or parse XMLs   
XmlConfiguration last = null;  
Object[] obj = new Object[args.length];  
for ( int i = 0; i < args.length; i++ )  
{  
    if ( args[i].toLowerCase().endsWith( ".properties" ) )  
    {  
        properties.load( Resource.newResource( args[i] ).getInputStream() );  
    }  
    else  
    {  
        XmlConfiguration configuration =  
            new XmlConfiguration( Resource.newResource( args[i] ).getURL() );  
        if ( last != null )  
            configuration.getIdMap().putAll( last.getIdMap() );  
        if ( properties.size() > 0 )  
            configuration.setProperties( properties );  
        obj[i] = configuration.configure();  
        last = configuration;  
    }  
}  
  
// For all objects created by XmlConfigurations, start them if they are lifecycles.  
for ( int i = 0; i < args.length; i++ )  
{  
    if ( obj[i] instanceof LifeCycle )  
    {  
        LifeCycle lc = (LifeCycle) obj[i];  
        if ( !lc.isRunning() )  
            lc.start();  
    }  
}
分爲兩步,先是依據xm描述的內容依次解析xml並處理邏輯,期間會生成不少個實例,若是實例實現了LifeCycle接口再依次調用start方法,所以server就是在此被start起來了。


嵌入式Jetty的啓動


很簡單的有木有,該server只有一個webapp的handler,所以只能服務一個應用,並且錯誤頁面天然也不是咱們常見的404頁面,雖然6000W作不了殺人機器,6000塊也是能夠作便宜的王太太百科全書的嘛!

相關文章
相關標籤/搜索