如何在Tomcat中为Web应用程序提供上下文配置?

时间:2011-08-22 01:30:10

标签: java tomcat java-ee

我有一个Web应用程序,它依赖于安装后要配置的一些资源和参数,比如JDBC连接。

我提出的是提供META-INF/context.xml,当我部署应用程序时,Tomcat将其复制到[engine-name]/[server-name]/[app-name].xml。这样我所提供的是一个war文件,可以复制到appBase文件夹(webapps)。 Tomcat的文档says如果有这样的文件,它将不会被覆盖,这真的很棒,因为部署后所做的更改不会丢失。

但这里有一个微妙的问题: 由于我们通过复制到webapps目录来部署应用程序,因此Tomcat将首先卸载现有应用程序以及配置文件。这样,配置文件将被丢失/覆盖,这是不可取的。 据我所知,Tomcat won't会修改此行为。

问题是: 有没有办法解决此问题,方法是以Tomcat不会删除现有配置文件的方式安装应用程序。 或者,有更好的方法来打包应用程序吗?

请注意,我们不希望将autoDeploy设置为false,并且我们不能使用人工干预进行安装(使用Tomcat Manager Web应用程序排除)。

如果我从.war文件中获取配置文件并将其单独复制为[engine-name]/[server-name]/[app-name].xml,则Tomcat仍会将其与我的应用程序关联,并在复制新的.war文件后将其删除。

另一个假设是:我们事先并不知道配置的值。我们将仅提供样本配置(占位符,如果您愿意),而实际配置将在稍后的某个时间执行(不一定在安装时间内)。

由于

6 个答案:

答案 0 :(得分:42)

解决方案很简单:不要将配置放在context.xml中。

这是我们使用的解决方案(适用于多种不同的外部客户):

我们有一场战争将在多个环境中使用,webapp.war。我们有三个环境,开发,集成和生产。集成和生产在客户现场。我们不知道客户端集成和生产站点的密码和文件路径。

我们结合使用两件事:JNDI查找数据库内容和外部属性文件。

在战争中提供的 context.xml 中,我们有一个ResourceLink

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

这提供了对全局定义的数据源的引用,该数据源在Tomcat的 server.xml 中定义。

<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来更改数据库详细信息。至关重要的是,这只需要为每个服务器执行一次,而不是重新部署。

在我们的弹簧配置中,要定义我们拥有的dataSource

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

对于其他属性,我们有一个全局的application.properties文件,该文件与webapp.war一起提供,但不是战争的一部分。这是由命令行上的-D引用来启动Tomcat。 -Duk.co.farwell.webapp.applicationDir="/usr/xxx/fff"。我们选择定义并读取属性文件。数据库的东西也可以通过这种方式完成,但我们将失去Tomcat完成的池化。

另一件事:如果移动服务器,或者由于某种原因机器被更改,我们不必重建。这是客户及其基础设施人员的事情。

答案 1 :(得分:10)

我设法以某种方式解决了这个问题。

1-在某个外部 Tomcat的appBase中安装一个展开的WAR目录,我们假设它在/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 / local / MyApp

中复制新版本的应用程序来更新应用程序

注意:

a)此解决方案也适用于未扩展的.war文件,但由于我们使用Spring的Log4JConfigListener,因此它不会从未爆炸的.war文件运行。 Tomcat不会将.war文件放在appBase(webapps)文件夹之外。

b)此方法不会阻止您在/usr/local/MyApp/META-INF/context.xml中使用context.xml,因为Tomcat在此配置中不会使用它。您可以在开发环境中使用它,将.war文件转储到appBase(webapps)文件夹中。

这是我到目前为止所做的,仍在寻找更好的解决方案。

答案 2 :(得分:5)

这就是我们如何设法从.WAR文件外部化webapp上下文

  1. 将.WAR文件放在tomcat之外的某个地方
  2. 在$ TOMCAT_HOME / conf / [Engine] / [Host] /目录中创建$ APP_NAME.xml文件。
  3. 现在提交&#34; $ APP_NAME.xml&#34;我们刚刚创建了需要具有上下文定义和参数+任何您想要特定于该上下文的EnvironmentVariable。
  4. 例如我有一个名为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>
    

    要访问这些环境变量,您必须在下面编写代码(Just lookup):

    InitialContext initialContext = new javax.naming.InitialContext();
    
    host = (String)initialContext.lookup("java:comp/env/webservice.host");
    port = (String)initialContext.lookup("java:comp/env/webservice.port");
    

答案 3 :(得分:4)

参考Apache Tomcat 5.5 Documentation

  

在$ CATALINA_HOME / conf / context.xml文件中:Context元素   信息将由所有webapps加载

您可以轻松尝试这种方法,它可能会有效,但我不确定这是否是一个很好的解决方案,尤其是如果您在Tomcat上运行多个Web应用程序。

答案 4 :(得分:1)

我不知道如何修改Tomcat的行为,但我可以想到两种不同的解决方案:

  1. 为每个环境构建不同的(参数化的)脚本,以便为构建脚本定义一个名为env的参数,并根据值在构建期间将特定于环境的context.xml置于WAR中。
  2. 为首先重新部署WAR文件的每个环境创建一个install脚本(将其放在webapps目录中),然后根据环境对Tomcat安装进行修改,例如: context.xml中的JDBC DataSource的不同主机名。
  3. 我大量使用后一种方法,因为它适用于企业环境。职责分离政策通常禁止开发团队了解例如生产数据库密码。选项#2解决了这个问题,因为只有IT操作在创建后才能访问特定于环境的安装脚本。

答案 5 :(得分:1)

@ n0rm1e:不确定tomcat是否为您提供任何解决方案。但一种可能的解决方案是: - 使用以下步骤创建一个ant脚本:

i)检查[engine-name] / [server-name]目录中是否存在.xml文件。如果存在,请备份/重命名。

ii)将您的war文件复制到tomcat webapps。重启tomcat服务器。

iii)将备份配置文件复制回[engine-name] / [server-name]目录