2011-08-22 124 views
40

我有一個Web應用程序,它依賴於一些資源和參數在安裝後進行配置,如JDBC連接。如何在Tomcat中爲Web應用程序提供上下文配置?

我想到的是提供一個META-INF/context.xml,當我部署應用程序時,它被Tomcat複製到[engine-name]/[server-name]/[app-name].xml。這樣我所提供的是一個可以複製到appBase文件夾(webapps)的war文件。 Tomcat的文檔says如果有這樣一個文件,它不會被覆蓋,這是非常好的,因爲部署後所做的更改不會丟失。

但是這裏有一個微妙的問題: 由於我們通過複製到webapps目錄來部署應用程序,Tomcat將首先卸載現有的應用程序以及配置文件。這樣配置文件將丟失/覆蓋,這是不可取的。據我所知, Tomcat won't修改了此行爲。

問題是: 有沒有辦法通過以Tomcat不會刪除現有配置文件的方式安裝應用程序來解決此問題。 或者,有沒有更好的方式打包應用程序?

請注意,我們不希望將autoDeploy設置爲false,並且我們無法使用人爲干預進行安裝(這會排除使用Tomcat Manager Web應用程序的情況)。

如果我從.war文件中取出配置文件並單獨複製它作爲[engine-name]/[server-name]/[app-name].xml,Tomcat仍然會將其與我的應用程序關聯,並在我複製新的.war文件後將其刪除。

另一個假設是:我們事先不知道配置的值。我們只會提供一個示例配置(如果您願意,可以使用佔位符),而實際配置將在稍後的某個時間執行(不一定在安裝時間內)。

感謝

+0

你不能從war中移除你的context.xml文件並直接放在tomcat需要的地方?它不會被卸載並重新安裝。在碼頭上,這是熱部署的方式 – Snicolas

+0

我試過,如果文件匹配[引擎]/[主機]/[應用] .xml模式,它被認爲是應用程序的一部分,即使它不是在.war文件(o_O)中。 – n0rm1e

+0

您不能爲所有不同的環境提供構建腳本,以便在部署後不需要修改任何內容? – home

回答

8

我設法以某種方式解決這個問題。

1-安裝一個展開的WAR目錄外部 Tomcat的appBase,我們假設它在/usr/local/MyApp。 [如果應用程序從未爆炸的戰爭中運行,則可以使用WAR文件代替WAR目錄。]

2-將上下文配置文件複製到[tomcat.conf]/[engine]/[hostname]目錄中,我們將其稱爲MyApp.xml。該文件將指向應用程序的位置:

<?xml version="1.0" encoding="UTF-8"?> 
<!-- Context configuration file for my web application --> 
<Context docBase="/usr/local/MyApp" privileged="true" antiResourceLocking="false" antiJARLocking="false"> 
     <Resource name="jdbc/myapp-ds" auth="Container" type="javax.sql.DataSource" 
       maxActive="100" maxIdle="30" maxWait="10000" username="XXX" password="XXX" 
       driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/mydb" /> 
</Context> 

3-您現在可以自由地修改配置文件。

4-更新通過在/ usr /本地/ MyApp的

注意複製你的應用程序的新版本的應用程序:

一)該解決方案適用於未展開.war文件爲好,但因爲我們使用Spring的Log4JConfigListener,它不會從未爆炸的.war文件運行。 Tomcat不會爆炸.war文件放在appBase(webapps)文件夾之外。

b)此方法不會阻止您在/usr/local/MyApp/META-INF/context.xml中使用context.xml,因爲Tomcat不會在此配置中使用它。您可以在您的開發環境中使用它,將您的.war文件轉儲到appBase(webapps)文件夾中。

這就是我到目前爲止仍在尋找更好的解決方案。

+0

您也可以看看Tomcat和Jetty都支持的Overlay Deployer:http://www.eclipse.org/jetty/documentation/current/overlay-deployer.html – n0rm1e

+0

上面的overlay-deployer鏈接不再起作用,但這裏似乎是:https://github.com/eclipse/jetty.project/tree/jetty-9.4.x/jetty-overlay-deployer –

1

我不知道如何修改Tomcat的行爲,但我能想到的2級不同的解決方案:

  1. 不同(參數)建立每個環境的腳本,讓你定義一個參數稱爲env添加到您的構建腳本,並根據它在構建期間將特定環境特定的context.xml放置在WAR中的值。
  2. 爲首先重新部署WAR文件(將其放置在webapps目錄中)的每個環境創建一個install腳本,然後根據環境對Tomcat安裝進行修改。 JDBC DataSource的不同主機名在context.xml中。

我大量使用後一種方法,因爲它適用於企業環境。職責分離政策通常會阻止開發團隊瞭解生產數據庫密碼。選項2解決了這個問題,因爲只有IT操作在創建後才能訪問特定於環境的安裝腳本。

+0

這是我想避免的情況:1-我們安裝應用程序並正確配置它。我們的基礎架構團隊會移動虛擬機並正確修改配置。大家都開心。 3-我們更新應用程序並部署一個新的.war文件。 4- BANG!步驟2中的更改丟失。 – n0rm1e

+0

如果我們可以強制應用程序在每次更新時重新配置,第二種方法就可以工作。如果我找不到更好的方式來發布應用程序,我們可能會這樣做。 – n0rm1e

1

@ n0rm1e:不確定tomcat是否爲您提供任何解決方案問題。但一種可能的解決方案可以是: - 用以下步驟創建一個螞蟻腳本:

i)檢查是否存在。xml文件在[engine-name]/[server-name]目錄中。如果存在,請備份/重命名它。

ii)將你的war文件複製到tomcat webapps。重新啓動tomcat服務器。

III)複製備份編輯配置文件回[引擎名]/[服務器名稱]目錄

+0

儘管我不喜歡這種方法,但我們最終這樣做了(在RPM預安裝和後安裝腳本中),因爲人們無法圍繞webapps文件夾以外的應用程序轉向他們的頭部:D – n0rm1e

38

解決方案很簡單:不要在你的context.xml中放置配置。

這裏是我們使用的解決方案(這對於許多各種各樣的外部客戶的效果很好):

我們將在多種環境下使用單一的戰爭,webapp.war。我們有三種環境,即開發,集成和生產。集成和生產在客戶現場。我們不知道客戶端集成和生產站點的密碼和文件路徑。

我們結合使用了兩件事情:數據庫內容和外部屬性文件的JNDI查找。

context.xml是在戰爭中傳遞,我們有一個ResourceLink

<ResourceLink name="jdbc/webapp" 
    global="uk.co.farwell.webapp.datasource.MySqlDataSource" /> 

這給了一個全局定義數據源,這是在server.xml爲Tomcat定義的參考。

<Resource auth="Container" 
      driverClassName="com.mysql.jdbc.Driver" 
      name="uk.co.farwell.webapp.datasource.MySqlDataSource" 
      password="xxx" url="xxx" username="fff" /> 

所以數據庫的詳細信息可以通過編輯server.xml不改變webapp.war改變。至關重要的是,這隻需要爲每個服務器完成一次,而不是重新部署。

在我們的Spring配置,定義dataSource我們:

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/webapp" /> 

對於其他性質,我們有與webapp.war一起提供一個全球性的application.properties文件,而不是一部分戰爭。在命令行上通過-D來引用它以啓動Tomcat。 -Duk.co.farwell.webapp.applicationDir="/usr/xxx/fff"。我們拿起定義並閱讀屬性文件。數據庫的東西也可以這樣完成,但是我們會失去Tomcat完成的池。

另一件事:如果服務器移動了,或者機器由於某種原因而改變了,我們不必重建。這是客戶及其基礎設施人員的事情。

+0

這是一個很好的方法。也許我們不應該關心JNDI數據源是如何在生產環境中配置的。 – n0rm1e

+2

我剛剛分手並將所有內容添加到全局context.xml文件中。 Tomcat有時會讓我的生活變得痛苦。 – HaxElit

+12

這對大多數情況非常有用。但是,如果您需要將同一個應用程序部署到多個上下文,而每個上下文都有不同的數據庫,則它將無法工作。 – Lachlan

4

通過參考Apache Tomcat 5.5 Documentation

在$ CATALINA_HOME/conf/context.xml文件文件:上下文元素 信息將被所有的webapps

你可以輕易嘗試這種方法被加載,它可能會工作,但我不確定這是否是一個好的解決方案,特別是如果您在Tomcat上運行多個webapps。

3

這就是我們如何管理外部化從.WAR web應用上下文文件

  1. 將您的.war文件之外的某個地方的tomcat
  2. 創建$ APP_NAME.xml文件到$ TOMCAT_HOME/conf目錄/ [引擎]/[主機] /目錄。
  3. 現在我們剛剛創建的文件「$ APP_NAME.xml」需要具有上下文定義和參數+您希望特定於該上下文的任何EnvironmentVariable。

例如,我有一個叫做VirtualWebApp的webapp。

我將創建像VirtualWebApp.xml文件下面上下文定義:

<Context docBase="/home/appBase/VirtualWebApp" path="/VirtualWebApp" reloadable="true"> 
    <Environment name="webservice.host" type="java.lang.String" value="1.2.3.4" /> 
    <Environment name="webservice.port" type="java.lang.String" value="4040" /> 
</Context> 

要訪問你必須寫下面的代碼,這些環境變量(只查找):

InitialContext initialContext = new javax.naming.InitialContext(); 

host = (String)initialContext.lookup("java:comp/env/webservice.host"); 
port = (String)initialContext.lookup("java:comp/env/webservice.port"); 
+0

請確保您爲查找條目添加了初始名稱空間「java:comp/env /」。 – srv

相關問題