引言 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塊也是能夠作便宜的王太太百科全書的嘛!