Web應用的框架
標準Jetty發布版本能部署標準servlet Spec Web應用和Jetty內部ContextHandler部署描述符,或者兩者的一個混合。
Web應用是可部署的動態(servlets、filters、jsps、等等)和靜態內容、支持庫、和綁定到特定上下文路徑的描寫性的元數據的集合。
格式和布局最終都是通過Servlet Spec定義,你可以查閱官方Servlet Spec文檔獲取關于Web應用布局和結構的更多細節,這里將給出一個基本的輪廓。
Web應用能被捆綁到一個單個的Web文件(WAR文件)或者作為一個文件夾樹:
1)/WEB-INF/
專門的Servlet API定義文件夾,通常存儲和Web應用相關但不為外部訪問的任何東西。
如果你有內容被你的Web應用內部訪問,但不會被web瀏覽器直接地訪問,你就應該把他們放在這里。
2)/WEB-INF/web.xml
必須的部署描述符,用于定義你的Web應用的各種行為。
3)/WEB-INF/classes/
Web應用的java classes文件放置目錄。
4)/WEB-INF/lib/
JAR文件放置的目錄。
自動的Web應用部署
為了部署Web應用,最簡單的方式就是放置你的WAR文件或者解壓后的WAR文件夾到${jetty.home}/webapps/,Jetty的部署掃描器將發現它,并部署它到同名的Context路徑下。
上下文路徑基于你的WAR的文件名(或文件夾名)。下面是一些例子(文件或文件夾名->上下文路徑):
/webapps/footrope.war ->http://host/footrope/
/webapps/baggywrinkle-1.0.war ->http://host/baggywrinkle-1.0/
/webapps/lazaret-2.1.3-SNAPSHOT.war ->http://host/lazaret-2.1.3-SNAPSHOT/
/webapps/belaying-pins/WEB-INF/web.xml ->http://host/belaying-pins/
/webapps/root.war (special name) ->http://host/
/webapps/root/WEB-INF/web.xml (special name) ->http://host/
配置特定的Web應用部署
用自動的Web應用部署方式是快速和簡單的,但有時你也許需要調整一些部署屬性(例如,你想指定一個上下文路徑而不是使用文件名,或者你想為這個Web應用指定一個特定的數據庫連接池),你可以使用Jetty Deployable Descriptor XML文件來實現。
Jetty支持通過XML文件部署Web應用,這些XML文件將構建一個Jetty能部署的ContextHandler實例。
使用基本的描述符文件
在默認的Jetty安裝中,Jetty掃描他的$JETTY_HOME/webapps文件夾查找上下文部署描述符文件,為了用這個文件部署一個web應用,只需要放置這個文件在那個文件夾中。
部署描述符文件自己是一個配置了一個WebAppContext類的XML文件。為了一個基本的安裝,你需要設置僅兩個屬性:
war:web應用文件(或文件夾)的文件路徑;
contextPath:web應用使用的上下文路徑。
例如,下面是是一個描述符文件,將/opt/myapp/myapp.war部署到上下文路徑/wiki:
/wiki /opt/myapp/myapp.war
或者你可以使用SystemProperty和Property元素在你的描述符文件中,如果你設置了系統屬性myapp.home=/opt/myapp,你能重寫上面的例子:
/wiki /myapp.war
如果你需要為你的應用修改home路徑,你僅需要改變系統屬性,這在有些場合非常有用。
配置高級描述符文件
如果你看WebAppContext類的文檔,你會發現它有許多屬性而不是僅僅有上面提到的兩項,下面是一些為你的描述符文件配置高級屬性的例子。
第一個例子告訴Jetty在部署WAR文件的時候不要解壓。這能幫助用戶避免修改解壓后的WAR,導致web應用下次部署的時候修改被還原。
/wiki /myapp.war false
下面的例子是獲取JavaEE Servlet上下文,并為它設置初始化參數。你也能使用setAttribute方法設置Servlet上下文屬性。然而,由于web應用的web.xml在部署描述符之后處理,web.xml值可能覆蓋你設置的屬性值。
/wiki /myapp.war myapp.config /config/app-config.xml
下面是設置一個指定的web.xml的覆蓋描述符的例子,該描述符在web應用的web.xml之后處理,因此它可以覆蓋web.xml中設置的同名屬性。當你想添加參數或者額外的附加Servlet mappings又不想修改壓縮的WAR文件的時候,可以采用這種方式。
/wiki /myapp.war /opt/myapp/overlay-web.xml
下面的例子不僅配置web應用上下文,而且配置一個數據庫連接池。
/wiki /myapp.war jdbc/DSTest org.some.Driver jdbc.url jdbc.user jdbc.pass
WebAppContext還有許多其它的設置項,具體可以參看WebAppContext的javadoc文檔。
部署WebAppContexts的處理
web應用在進入service之前,需要一些處理:解壓、為它們的jar指定classloader、web.xml和web-fragment.xml描述符處理、類的注釋掃描。當web應用變得更加復雜時,我們增加方法幫助你在部署時添加或者減少處理的數量。在這節我們將學習部署處理和你怎么裁剪它。
Jetty的配置類
當一個webapp正在被部署時,一系列org.eclipse.jetty.webapp.Configuration類將被應用到它,它們中的每一個都履行一個特定的功能。這些配置的順序是有意義的,后續的配置在先前的配置基礎上處理。下面是被應用到每一個org.eclipse.jetty.webapp.WebAppContext的配置列表,按順序:
org.eclipse.jetty.webapp.WebInfConfiguration -> 抽取war,整理jars和定義classpath
org.eclipse.jetty.webapp.WebXmlConfiguration -> 處理WEB-INF/web.xml文件
org.eclipse.jetty.webapp.MetaInfConfiguration -> 為META-INF/resources和META-INF/web-fragment.xml查看container和webapp jars
org.eclipse.jetty.webapp.FragmentConfiguration -> 處理所有的發現的META-INF/web-fragment.xml文件
org.eclipse.jetty.webapp.JettyWebXmlConfiguration -> 處理WEB-INF/jetty-web.xml文件
一個配置類的結構
一個配置類在WebAppContext的生命周期中有五個階段:
1)preConfigure:在WebAppContext啟動時執行。配置應該發現它在后續的階段需要的所有資源;
2)configure:這個階段將執行配置類的工作,通常會使用在preConfigure階段發現的資源;
3)postConfigure:這個階段配置將清理上一個階段創建的一些資源,這些資源在WebAppContext的生命周期中將不再需要;
4)deconfigure:這個階段在WebAppContext被停止時出現,允許配置撤銷它創建的資源/元數據;
5)destroy:這個階段在WebAppContext從service移除時調用,例如:和它相關的war文件將從$JETTY_HOME/webapps文件夾中刪除。
每個配置類的每個階段都按照配置類的配置順序被調用,例如,用默認配置類作為例子,preConfigure()被調用的順序依照WebInfConfiguration、WebXmlConfiguration、MetaInfConfiguration、FragmentConfiguration、最后JettyWebXmlConfiguration,這個循環又開始在configure()階段,然后是postConfigure()階段,循環再次重復在deconfigure(),最終在destroy()階段。
通過創建額外的配置擴展容器支持
由上所述,有一個默認的配置集合支持基本的webapp部署。你將注意到我們沒有提到一些JavaEE特征,例如JNDI,也沒有提到高級servlet spec特征,例如注釋。那是因為Jetty的哲學是允許用戶按照自己的需要裁剪容器。如果你不需要這些特征,那么你不需要為它們付出代價 - 一個重要的考慮是因為這些特征例如注釋需要大量的和耗時的WEB-INF/lib包的掃描,這些都可能成為部署延遲的源頭。我們將在下面的“其它配置”中看到另一個Jetty提供的webapp工具,可以幫助削減分析jar包的時間消耗。
Jetty采用插件的方式提供對JNDI和注釋的支持。
首先,讓我們看看怎么支持JNDI。
我們需要用到兩個額外的配置:
org.eclipse.jetty.plus.webapp.EnvConfiguration -> 創建java:comp/env為webapp,應用WEB-INF/jetty-env.xml文件
org.eclipse.jetty.plus.webapp.PlusConfiguration -> 處理JNDI關聯的WEB-INF/web.xml標記,并且與名目掛鉤
這些配置必須按照上面的順序添加,并且應該在配置列表中的org.eclipse.jetty.webapp.JettyWebXmlConfiguration前被插入。支持JNDI的細節將在后面用一個單獨的章節講解。
下面來看看怎么注釋。我們需要僅一個額外的配置類幫助提供servlet注釋掃描:
org.eclipse.jetty.annotations.AnnotationConfiguration -> 掃描容器和web app jars查找@WebServlet、@WebFilter、@WebListener等
上面的配置必須在org.eclipse.jetty.webapp.JettyWebXmlConfiguration之前插入。注釋的配置細節也將在后面用一個單獨的章節講解。
怎么設置配置列表
你可以為Jetty指定一個不同的配置列表,通過下面的方式。
1)直接在WebAppContext中設置配置列表
如果你僅希望影響一個webapp,這可能是最容易的方式。你可以通過上下文配置文件或者代碼來設置配置列表,下面是一個例子怎么為JNDI和注釋添加配置:
/webapps/my-cool-webapp - org.eclipse.jetty.webapp.WebInfConfiguration
- org.eclipse.jetty.webapp.WebXmlConfiguration
- org.eclipse.jetty.webapp.MetaInfConfiguration
- org.eclipse.jetty.webapp.FragmentConfiguration
- org.eclipse.jetty.plus.webapp.EnvConfiguration
- org.eclipse.jetty.plus.webapp.PlusConfiguration
- org.eclipse.jetty.annotations.AnnotationConfiguration
- org.eclipse.jetty.webapp.JettyWebXmlConfiguration
2)通過部署器為所有的webapp設置配置列表
如果你用部署器(deployer),你能在WebAppProvider設置配置列表,它們將被應用到每一個被部署器部署的WebAppContext。
/webapps - org.eclipse.jetty.webapp.WebInfConfiguration
- org.eclipse.jetty.webapp.WebXmlConfiguration
- org.eclipse.jetty.webapp.MetaInfConfiguration
- org.eclipse.jetty.webapp.FragmentConfiguration
- org.eclipse.jetty.plus.webapp.EnvConfiguration
- org.eclipse.jetty.plus.webapp.PlusConfiguration
- org.eclipse.jetty.annotations.AnnotationConfiguration
- org.eclipse.jetty.webapp.JettyWebXmlConfiguration
3)添加或者插入到一個存在的列表
你可以將配置類添加或者插入一個已經存在的配置列表,下面是一個例子,它實現了為JNDI添加一個配置支持 - 你可以通過xml配置文件按,或者通過代碼,這里使用配置文件,實際上它是Jetty發布版本的$JETTY_HOME/etc/jetty-plus.xml:
org.eclipse.jetty.webapp.FragmentConfiguration - org.eclipse.jetty.plus.webapp.EnvConfiguration
- org.eclipse.jetty.plus.webapp.PlusConfiguration
org.eclipse.jetty.webapp.Configuration.ClassList類提供了下面的方法:
1)addAfter:在給出的配置類名的后面插入提供的配置類列表;
2)addBefore:在給出的配置類名之前插入提供的配置類列表。
其它配置org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern
這是一個上下文屬性,用于設置在an org.eclipse.jetty.webapp.WebAppContext,控制容器的classpath的哪些部分應該為一些特性做處理,這些特性包括:注釋、META-INF/resources、META-INF/web-fragment.xml等。
屬性的值是一個正則表達式,下面是一個例子,使用xml文件(也可以用代碼),指定匹配任何名字以“foo-”或者“bar-”開始的jar,或者名字為classes的文件夾:
org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern .*/foo-[^/]*\.jar$|.*/bar-[^/]*\.jar$|.*/classes/.*
注意配置的順序決定了jar或者class文件夾掃描的順序。
org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern
和上面類似,這個屬性控制哪個jar因為注釋和META-INF下的資源被處理。然而,這個屬性只處理webapp的classpath(通常是WEB-INF/lib)下的jar。當你有許多jar在WEB-INF/lib中,但你知道只有少數的jar需要被掃描的時候特別有用。
下面是一個例子,這里只匹配以“spring-”開頭的jar:
org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern .*/spring-[^/]*\.jar$
注意配置的順序決定了jar掃描的順序。
配置靜態內容部署
你可以用Jetty部署描述符文件和內部的ResourceHandler設置簡單的靜態內容服務。僅需要在${jetty.home}/webapps文件夾中創建一個文件scratch.xml,然后粘貼這些文件內容在它里面。
/scratch /home/jesse/scratch true
這是一個很基本的靜態文件服務設置,如果你想要你寫高級設置,可以使用DefaultServlet。
熱部署
Jetty可以通過監聽一個文件改變來部署任意的上下文或者web應用。如果你增加一個web應用或一個上下文描述符到這個文件夾,Jetty的DeploymentManager(DM)將部署一個新的上下文。如果你接觸或者更新一個上下文描述符,DM停止、重配置、并重新部署它的上下文。如果你移除一個上下文,DM停止它,并從server移除它。
為了控制這個行為,你將需要配置一些WebAppProvider屬性。
1)monitoredDirName:需要掃描的可能部署web應用(或部署描述符xml文件)的文件夾;
2)scanInterval:提供的monitoredDirName的掃描周期,單位秒;0表示不支持熱部署。
這個配置默認的位置是在${jetty.home}/etc/jetty-deploy.xml文件中。
org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern .*/servlet-api-[^/]*\.jar$ /webapps /etc/webdefault.xml 1 true
更多的細節將在“部署架構”中講解。
部署架構
Jetty圍繞一個可擴展的部署管理器架構構建,這個架構包括它內部的Web應用的生命周期。
為了讓Jetty提供內容服務(靜態或動態),你需要創建一個ContextHandler,并在適當的位置添加它到Jetty。在Jetty 7增加的可插拔的DeploymentManager使這個過程變得更加容易。Jetty發布中包含了DeploymentManager的例子,部署WAR文件并部署Jetty context.xml文件到Jetty。
DeploymentManager是webapp部署機制的核心;它包含一個應用生命周期圖(Application LifeCycle Graph),應用提供者(Application Provider),和在圖中的一組綁定。應用提供者負責發現和提供應用到應用生命周期圖,圖中的綁定用于控制部署過程。
應用提供者(Application Providers)
Jetty部署一個應用前,一個AppProvider標識這個APP,然后提供它到DeploymentManager。Jetty發布中主要的AppProvider是WebAppProvider。
應用生命周期圖(Application LifeCycle Graph)
DeploymentManager的核心特征是應用生命周期圖。
圖的節點和邊在Jetty中是預定義的,根據最通常的行為和狀態發現,但它們并不是硬編碼的,你能根據你的需要調整和添加它們。
新的應用在Undeployed節點進入這個圖,然后java.lang.String DeploymentManager.requestAppGoal(App,String)方法推動他們通過整個圖。
生命周期綁定(LifeCycle Bindings)
一組默認的AppLifeCycle.Bindings定義標準行為,并處理部署、啟動、停止和卸載應用。你能寫你自己的AppLifeCycle.Bindings,然后分配它們到應用生命周期圖的任何地方。
你寫的AppLifeCycle.Binding可以包括:
1)驗證進入的應用;
2)阻止已知的被禁止的應用的部署;
3)在一個協作的環境中,提交安裝到應用審計服務;
4)分發應用到在蔟(cluster)或云(cloud)中的其它節點;
5)通知應用狀態改變的owner/admin。
有四個默認的綁定:
1)StandardDeployer:在合適的位置部署ContextHandler進入Jetty;
2)StandardStarter:設置ContextHandler到started,開始接收輸入請求;
3)StandardStopper:停止ContextHandler,停止接收輸入請求;
4)StandardUndeployer:從Jetty中移除ContextHandler。
還有一個非標準的綁定,叫Debug Binding,用于debugging,它為通過應用生命周期的各種轉換記錄日志。
理解默認的WebAppProvider
WebAppProvider為WAR文件、文件夾或Jetty部署描述符XML文件提供部署。它支持熱部署。
WebAppProvider的基本操作是為部署預掃描文件夾。在標準Jetty發布中,這被配置在${jetty.home}/etc/jetty-deploy.xml文件。
/webapps /etc/webdefault.xml 1 true
上面的配置將創建一個DeploymentManager,并作為一個Server LifeCycle Bean。
1)contexts
一個HandlerContainer引用,通常在${jetty.home}/etc/jetty.xml文件中的id="Contexts"的項,是一個ContextHandlerCollection的實例。
2)monitoredDirName
一個指向文件夾的文件路徑或者URL,用于掃描web應用。掃描按照下面的規則:
(1)Base文件夾必須存在
(2)隱藏文件("."開頭的文件)被忽略
(3)以".d"結尾的文件夾被忽略
(4)通常的CVS文件夾"CVS"和"CVSROOT"被忽略
(5)任何*.war文件被自動部署
(6)任何*.xml文件被作為上下文描述符部署
(7)當WAR文件和XML文件有相同的base那么,那么WAR文件不被部署,XML文件被認為配置和引用WAR文件
(8)文件夾是可部署的
(9)文件夾和WAR文件同名,文件夾不被部署,WAR文件被認為和文件夾相同并自動部署
(10)文件夾和XML文件同名,文件夾不被部署,XML文件認為配置和引用文件夾
(11)其它所有文件夾采用自動部署
(12)如果自動部署被用,文件名root.war或者文件夾名root將部署到"/"上下文路徑
3)defaultsDescriptor
指定默認的servlet web描述符供所有web應用使用。描述符的目的是在web應用自己的/WEB-INF/web.xml被應用前,為web應用提供共同的配置。Jetty發布中自帶的${jetty.home}/etc/webdefault.xml控制JSP和默認servlets的配置。
4)scanInterval
monitoredDirName文件夾的掃描周期,單位秒,掃描包括:新的上下文需要部署,改變的上下文重部署,和移除的上下文卸載。
5)extractWars
如果參數為true,任何WAR或者zip文件在部署之前被先提取到一個臨時的文件夾。如果在web應用中有未編譯的JSP,這樣做是很好的。
6)parentLoaderPriority
參數是一個布爾變量,選擇標準Java parent first delegation被使用,或者servlet specification webapp classloading priority。后者是默認。
快速啟動Webapps
Servlet的自動發現特征會使部署慢且不確定。web應用配置的自動發現在webapp的部署中是有用的,它允許通過指定jar文件來激活新的特征和框架。然而,為了部署,需要掃描一些jar包的內容,導致webapp啟動時間延遲。
從Jetty的9.2.0.M0版本開始,增加了快速啟動模塊,允許webapp被預掃描和預配置。這意味著所有的掃面將在部署之前完成,所有需要部署的項都將在部署之前準備好。所有的配置都會被編碼到一個有效的web.xml中,叫WEB-INF/quickstart-web.xml,quickstart-web.xml文件不僅包含所有的Servlets、Filters和Constraints,而且它也編碼為所有發現的上下文參數:
1)ServletContainerInitializers
2)HandlesTypes classes
3)Taglib Descriptors
使用快速啟動機制,jetty能完全繞過所有掃描和發現模型,快速啟動一個webapp。
設置快速啟動
為了使用宏快速啟動,模塊對jetty實例必須是可用的。在maven項目中僅需要添加一個在artifact ID為jetty-quickstart的依賴,或者使用下面的命令啟動jetty發布版本:
>java -jar $JETTY_HOME/start.jar --add-to-startd=quickstart
同時你部署的webapps需要是org.eclipse.jetty.quickstart.QuickStartWebApp的實例,而不是通常的org.eclipse.jetty.webapp.WebAppContext。如果你的web應用已經有一個webapps/myapp.xml文件,則你能簡單的改變配置元素中的這個類,否則你需要創建一個如下的webapps/myapp.xml文件:
/benchmark.war /benchmark true
預配置web應用
如果QuickStateWebApp的方法setAutoPreconfigure(true)被調用(看上面myapp.xml的例子),那么webapp第一次部署時,一個WEB-INF/quickstart-web.xml文件將被產生,它包含了所有發現的配置。在接下來的部署中,所有的掃描將被跳過,quickstart-web.xml被直接用于配置web應用。
也可以通過手動的運行類org.eclipse.jetty.quickstart.PreconfigureQuickStartWar來預配置一個war文件,如下:
>java -cp jetty-all-9.2.0.jar:servlet.jar org.eclipse.jetty.quickstart.PreconfigureQuickStartWar
這將在第一次配置之前創建一個quickstart-web.xml文件。注意這也能是發現配置的好的調試工具。運行類似若不帶參數可以看到運行它的其它選項。
用預編譯JSP避免TLD掃描
預編譯JSP是提高web應用啟動時間的好方法,從jetty 9.2.0開始,apache Jasper JSP實現被使用,允許TLD掃描被略過。這可以通過增加一個上下文參數到web.xml文件做到(這可以通過使用Jetty Maven JSPC插件自動做到):
org.eclipse.jetty.jsp.precompiled true
繞過start.jar
Jetty Start.jar是一個非常有力和靈活的機制,用于構造一個classpath和執行編碼在jetty xml格式的配置。然而,這個機制在構造classpath時需要花費時間。start.jar可以通過使用-dry-run選項繞過start.jar機制:
>RUN=$(java -jar $JETTY_HOME/start.jar --dry-run)>eval $RUN
看文倉www.kanwencang.com網友整理上傳,為您提供最全的知識大全,期待您的分享,轉載請注明出處。
歡迎轉載:http://www.kanwencang.com/bangong/20170106/82865.html
文章列表