WAR文件与具有嵌入式服务器的Java应用程序
大多數服務器端Java應用程序(例如,面向Web或面向服務的)都希望在容器中運行。 打包這些應用程序以進行分發的傳統方法是將它們捆綁為WAR文件。 這無非是具有標準目錄布局的ZIP歸檔文件,其中包含運行時所需的所有庫和應用程序級依賴項。 這種格式幾乎可以互操作,并且可以部署到您喜歡的任何服務器容器,Tomcat或Jetty,JBoss或GlassFish等。
但是,還有另一種流派完全顛覆了這種模式。 通過這種方法,Java應用程序像任何普通應用程序一樣被打包用于命令行執行。 嵌入式容器不是部署到容器,而是部署在應用程序本身中!
這對于使用多種語言的課程來說是一樣的。 適用于Python的Django框架包括用于開發和測試的捆綁服務器,而Ruby on Rails附帶了一個用于生產的嵌入式服務器。 這個概念在Java中已經存在了一段時間, Jetty專攻嵌入式利基市場。 但是,這與規范相去甚遠,事實上的標準仍然是可以部署到Tomcat的WAR文件。
但是,嗡嗡聲越來越大。 在去年的DevNexus會議上,我參加了James Ward的會議,當時他是Heroku的“開發者”。 捆綁您自己的容器是將應用程序部署到Heroku的基于云的平臺的推薦方法,而James是一個大力支持者 。
他的會議專門針對Java和Scala的Play框架,該框架以類似于Rails服務器的方式嵌入Netty 。 與Grails不同, Grails使用Django風格的服務器進行開發,然后將其作為WAR文件發布,而Play則打算在生產過程中一直使用自己的服務器。 James在所有Java應用程序中都倡導了這種方法。
一場嵌入式冒險
我至少喝了一口Kool-Aid。 當我開始編寫示例Hibernate Search by Example時 ,我想將重點放在Hibernate Search上,而不是其他任何框架或服務器問題上。 因此,我避開了Spring,并使用普通的Servlet 3.0方法編寫了本書的示例應用程序。
我通常在自己的開發環境中使用Eclipse,并將其指向本地Tomcat實例以測試Web應用程序。 但是,我想為喜歡使用IntelliJ,Netbeans或根本不使用IDE的讀者提供支持。 因此,我決定將構建腳本嵌入測試服務器,以便讀者可以運行示例而無需安裝或配置任何東西。
在Maven中使用嵌入式服務器
我的第一個目標只是從我的Maven構建腳本中啟動服務器,因此讀者不必安裝服務器或將其集成到IDE中。 我以前看過這件事,這很簡單,只需將Jetty Maven插件添加到項目的POM中即可。 讀者應該能夠使用以下命令構建示例應用程序并一步啟動它:
mvn clean jetty:run嗯,不是那么快。 您應該能夠對靜態內容進行更改,并看到更改在服務器運行時立即生效。 但是,我遇到了有關文件被鎖定的錯誤。 在花了一些時間進行研究之后,我發現Jetty的默認設置在Windows文件鎖定中效果不佳。 可以通過在一個配置文件中切換一個屬性來解決此問題。
但是,您必須打開Jetty JAR文件才能獲取此配置文件的正確副本。 首先,你要挖圍繞本地Maven回購,并找出哪些 JAR文件破解打開(它原來是碼頭,web應用,而不是碼頭服務器)。 一旦獲得了webdefault.xml文件的副本并切換了useFileMappedBuffer設置,就必須將副本保存在項目中的某個位置,并更新Maven POM以在此處查找而不是在Jetty JAR內部查找:
<plugin><groupId>org.mortbay.jetty</groupId><artifactId>jetty-maven-plugin</artifactId><version>8.1.7.v20120910</version><configuration><webAppConfig><defaultsDescriptor>${basedir}/src/main/webapp/WEB-INF/webdefault.xml</defaultsDescriptor></webAppConfig></configuration> </plugin>好吧……比我預期的麻煩得多,但是我可以解決這個問題。
將嵌入式服務器與其他構建系統一起使用
我知道許多Java開發人員都討厭Maven。 因此,我想提供使用Ant構建的本書示例應用程序的版本,以說明如何適應默認概念。 那么,我應該在build.xml中添加哪一行以使Ant使用Jetty?
嗯,不是那么快。 有 用于碼頭Ant集成 ,但它比Maven的更繁瑣。 即使您使用的是Ivy之類的依賴項管理系統,您的Ant腳本也無法為您下載和管理嵌入式服務器。 相反,您必須下載完整的獨立Jetty服務器,然后手動將其片段復制到您的項目中。 誰不希望將6兆的可執行二進制文件提交到源代碼管理中?
在Jetty服務器JAR上復制后,您需要手動添加另一個JAR文件以進行Ant集成。 令我驚訝的是,我發現最新的受支持版本是Jetty 7,實現了將近8年的Servlet 2.5規范。
我看到他們終于在上個月添加了Jetty 8,但是當我去年秋天寫這本書時,這對我沒有幫助。 我不得不為Servlet 2.5(而不是3.0)重寫這個示例應用程序版本,并且開始懷疑這是否真的值得。
通過代碼使用嵌入式服務器
本書的最后這一章討論了在集群服務器環境中運行的Hibernate Search應用程序。 Maven插件純粹是單實例的,因此我決定編寫一個小的引導程序類,該類將在語法上在不同端口上啟動兩個Jetty實例。 通過將此類構造為JUnit測試,我仍然可以讓Maven像這樣自動啟動它:
嗯,不是那么快。 啟動時未注冊我的應用程序的Servlet,偵聽器和RESTful服務。 經過大量浪費的研究時間后,我發現有很多不同的Jetty “風味”可用,默認情況下啟用或禁用Servlet 3.0功能(例如注釋)。
老實說,我仍然不完全了解如何分辨“高潮”和“非高潮”之間的區別。 我只能告訴您的是,為了使注釋能夠正常工作,我必須將這段代碼添加到我的bootstrap類中:
... masterContext.setConfigurations( new Configuration[] { new WebInfConfiguration(), new WebXmlConfiguration(), new MetaInfConfiguration(), new FragmentConfiguration(), new EnvConfiguration(), new PlusConfiguration(), new AnnotationConfiguration(), new JettyWebXmlConfiguration(), new TagLibConfiguration() } ); ...比將WAR文件拖放到Tomcat的/ webapps文件夾中更簡單,更直觀,對嗎?
從控制臺和云使用嵌入式服務器
完成本書后,我希望將示例代碼的演示版本推送到GitHub并部署到Heroku 。 從理論上講,Heroku可以運行可以從命令行在本地運行的任何應用程序。 如果Heroku找到Maven POM,它將運行mvn clean程序包,然后執行您在名為Procfile的腳本中放置的所有啟動命令。
我的程序化Jetty啟動器在Maven運行的情況下運行良好。 但是,Maven在測試時正在管理我的類路徑依賴項,現在我需要在沒有該幫助的情況下可以使用Jetty。 Heroku在其演示Java應用程序中使用的推薦方法是將您的應用程序與Tomcat的一個文件版本捆綁在一起。 太棒了,無論如何,我還是更熟悉Tomcat!
嗯,不是那么快。 如果您的應用程序希望將數據庫連接(或其他任何內容)注冊為JNDI資源,那么您就自己決定了。 Heroku捆綁的Tomcat運行程序不支持JNDI設置。 嗯......也許這就是為什么Heroku的香草servlet的演示并沒有真正做什么,以及為什么只演示應用程序, 并做一些事情,而不是是基于Spring。 現在,我考慮了一下,James Ward去年離開了Heroku,為TypeSafe工作,自從他離開后,Heroku就沒有對其Java網站進行任何更新。 喝了
不用擔心,因為有一個類似的單文件Jetty Runner ,它確實允許您將JNDI設置作為命令行參數傳遞。 此外,我們已經投入了大量時間來解決嵌入式Jetty的所有問題!
嗯,還是太快了。 如果您在JSP視圖中使用JSTL taglib(即您生活在21世紀),那么Jetty Runner會讓您陷入混亂 。 從命令行運行它時,您需要將參數傳遞給Java,以實現以下目的:
(*)您沒看錯。 經過所有這些嵌入式噩夢之后,Heroku 實際上仍在使用WAR文件 !
我的Heroku個人資料最終看起來像這樣:
web: java $JAVA_OPTS -jar target/dependency/jetty-runner-8.1.7.v20120910.jar --lib target/hibernate-search-demo-0.0.1-SNAPSHOT/WEB-INF/lib --port $PORT --jdbc org.apache.commons.dbcp.BasicDataSource "url=jdbc:h2:mem:vaporware;DB_CLOSE_DELAY=-1" "jdbc/vaporwareDB" target/*.war這里有多個類加載器在工作,這使Jetty Runner可以從其類路徑而不是Web應用程序的類路徑加載JSTL / taglib東西。
結論
從一開始就將嵌入式服務器概念嵌入框架中,嵌入式服務器概念就沒有本質上的錯誤。 編寫Play應用程序是一種樂趣,將它們部署在Heroku上幾乎是微不足道的。 在日常工作中,我使用一個名為hybris的基于Spring的商務軟件包,該軟件包的擴展構建系統將Tomcat服務器捆綁到您的應用程序中。 只要您不需要過多地定制構建腳本,就可以正常工作。
另一方面,該概念對于廣泛的通用用途而言太脆弱和脆弱。 用管道將嵌入式服務器連接到普通Java應用程序上純屬痛苦。 您也許可以堅持別人的工作示例的安全性,但是當您的應用執行任何不同的操作時,您就可以自行解決損壞問題。 將我的嵌入式冒險帶入上面,并將其與使用Tomcat的“麻煩”進行對比:
我獲得的唯一真正優勢是能夠在Heroku上運行演示的能力。 但是,來自云提供商的Java支持每天都在提高。 Jelastic允許您立即將普通的WAR文件部署到Tomcat 7或GlassFish 3。 AppFog支持部署到Tomcat 6 ,即將支持Tomcat 7 。 我懷疑在不久的將來, 修改應用程序以進行云部署的想法將被視為不合時宜。
簡而言之,這取決于您使用的框架。 如果嵌入式服務器是嵌入式的,那么它們可能會很酷。 如果將它們用膠帶固定,則可能會很可怕。 如果我今天寫的是Hibernate Search by Example ,示例應用程序構建腳本將產生兩件事:一個WAR文件和一個Tomcat下載鏈接。
翻譯自: https://www.javacodegeeks.com/2014/03/war-files-vs-java-apps-with-embedded-servers.html
總結
以上是生活随笔為你收集整理的WAR文件与具有嵌入式服务器的Java应用程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 缘去掉绞丝旁是什么字 缘去掉绞丝旁是彖吗
- 下一篇: JavaFX自定义控件– Nest Th