如何在 Tomcat 中为 Web 应用程序提供上下文配置?
我有一个 Web 应用程序,它依赖于安装后配置的一些资源和参数,例如 JDBC 连接。
我想出的是提供一个 META-INF/context.xml
,将其复制到 [engine-name]/[server-name]/[app-name].xml< /code> 当我部署应用程序时由 Tomcat 执行。这样,我提供的只是一个可以复制到 appBase 文件夹(webapps)中的 war 文件。 Tomcat的文档说如果存在这样的文件,它不会被覆盖,这确实是太好了,因为部署后所做的更改不会丢失。
但这里有一个微妙的问题: 由于我们通过复制到 webapps 目录来部署应用程序,Tomcat 将首先卸载现有的应用程序以及配置文件。这样配置文件将丢失/被覆盖,这是不可取的。 据我所知,Tomcat 不会修改此行为。
问题是: 有没有办法通过以 Tomcat 不会删除现有配置文件的方式安装应用程序来解决此问题。 或者,有更好的方法来打包应用程序吗?
请注意,我们不想将 autoDeploy 设置为 false,并且无法使用人工干预进行安装(这排除了使用 Tomcat Manager Web 应用程序)。
如果我从 .war 文件中获取配置文件并将其单独复制为 [engine-name]/[server-name]/[app-name].xml
,Tomcat 仍会将其与我的应用程序并在复制新的 .war 文件后将其删除。
另一个假设是:我们事先不知道配置的值。我们只会提供示例配置(如果您愿意,可以提供占位符),而实际配置将在稍后的某个时间(不一定是在安装时)执行。
谢谢
I have a web application that relies on some resources and parameters to be configured after it is installed, like a JDBC connection.
What I have come up with is providing a META-INF/context.xml
which is copied into [engine-name]/[server-name]/[app-name].xml
by Tomcat when I deploy the application. This way all I am providing is a war file that can be copied into the appBase folder (webapps).
Tomcat's documentation says if there is such a file it won't be overwritten which is really great, since the changes made after deployment won't be lost.
But there is a subtle issue here:
Since we deploy the application by copying into webapps directory, Tomcat will first uninstall the existing application as well as the configuration file. This way the configuration file will be lost / overwritten which is not desirable.
Tomcat won't modify this behaviour as far as I know.
The question is:
Is there a way to work around this issue by installing the application in a way that Tomcat won't remove the existing configuration file.
Or, is there a better way of packaging the application?
Please note that we don't want to set autoDeploy to false and we cannot use human intervention for the installation (which rules out using Tomcat Manager web application).
If I get the configuration file out of .war file and copy it separately as [engine-name]/[server-name]/[app-name].xml
, Tomcat will still associate it with my application and remove it once I copy a new .war file.
Another assumption is: We don't know in advance the values to the configuration. We will only provide a sample configuration (a placeholder, if you wish) while actual configuration will be performed at some time later (not necessarily in the installation time).
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
解决方案很简单:不要将配置放入 context.xml 中。
这是我们使用的一个解决方案(对于许多不同的外部客户来说效果很好):
我们有一个将在多个环境中使用的战争,webapp.war。我们有三个环境:开发、集成和生产。集成和生产均在客户现场进行。我们不知道客户端集成和生产站点的密码和文件路径。
我们结合使用两种方法:数据库内容的 JNDI 查找和外部属性文件。
在战争中交付的
context.xml
中,我们有一个ResourceLink,它提供了对全局定义的数据源的引用,该数据源在<中定义Tomcat 的 code>server.xml。
因此,可以通过编辑
server.xml
来更改数据库详细信息,而无需更改webapp.war
。至关重要的是,这只需要为每个服务器执行一次,而不是在重新部署时执行。在我们的 spring 配置中,为了定义 dataSource,我们有:
对于其他属性,我们有一个全局 application.properties 文件,它与 webapp.war 一起交付,但不是 war 的一部分。这是由命令行上的
-D
引用来启动 Tomcat。-Duk.co.farwell.webapp.applicationDir="/usr/xxx/fff"
。我们获取定义并读取属性文件。数据库的东西也可以用这种方式完成,但我们会失去 Tomcat 完成的池化。另一件事:如果服务器被移动,或者机器由于某种原因被改变,我们不必重建。这是客户及其基础设施人员的问题。
The solution is simple: don't put configuration in your context.xml.
Here is a solution that we use (which works well for a number of diverse external customers):
We have a single war which will be used in multiple environments, webapp.war. We have three environments, development, integration and production. Integration and production are at the customer site. We don't know passwords and file paths for the client integration and production sites.
We use a combination of two things: JNDI lookup for database stuff and external properties files.
In the
context.xml
that is delivered in the war, we have a ResourceLinkThis gives a reference to a globally defined data source, which is defined in the
server.xml
for Tomcat.So the database details can be changed by editing the
server.xml
without changing thewebapp.war
. Crucially, this only needs to be done once for each server, not at redeploy.In our spring configuration, to define the
dataSource
we have:For other properties, we have a global application.properties file which is delivered along with the webapp.war, but is not part of the war. This is referenced by a
-D
on the command line to start Tomcat.-Duk.co.farwell.webapp.applicationDir="/usr/xxx/fff"
. We pick up the definition and read the properties file. The database stuff could be done this way as well, but we'd lose the pooling done by Tomcat.Another thing: we don't have to rebuild if servers are moved, or if machines are changed for some reason. This is a matter for the customer and their infrastructure people.
我设法以某种方式解决了这个问题。
1- 在 Tomcat 的 appBase外部某处安装分解的 WAR 目录,假设它位于
/usr/local/MyApp
中。 [如果您的应用程序从未展开的 war 运行,则可以在此步骤中使用 WAR 文件而不是 WAR 目录。]2- 将上下文配置文件复制到
[tomcat.conf]/[engine]/[hostname]< /code> 目录,我们将其命名为
MyApp.xml
。该文件将指向应用程序的位置:3- 您现在可以自由地修改配置文件。
4- 通过在 /usr/local/MyApp 中复制应用程序的新版本来更新应用程序
注意:
a) 此解决方案也适用于未展开的 .war 文件,但由于我们使用 Spring 的 Log4JConfigListener,因此它不会从未展开的 .war 文件运行。战争文件。 Tomcat 不会分解放在 appBase (webapps) 文件夹之外的 .war 文件。
b) 此方法不会阻止您在 /usr/local/MyApp/META-INF/context.xml 中包含 context.xml,因为在此配置中 Tomcat 不会使用它。您可以在开发环境中使用它,将 .war 文件转储到 appBase (webapps) 文件夹中。
这是我到目前为止所得到的,仍在寻找更好的解决方案。
I managed to resolve this issue somehow.
1- Install an exploded WAR directory somewhere outside Tomcat's appBase, let's assume it is in
/usr/local/MyApp
. [You can use a WAR file for this step instead of WAR directory, if your application runs from an unexploded war.]2- Copy the context configuration file into
[tomcat.conf]/[engine]/[hostname]
directory, let's call itMyApp.xml
. This file will point to the location of the application:3- You are now free to go and modify the configuration file.
4- Update the application by copying new version of your application in /usr/local/MyApp
Notes:
a) This solution applies to an unexpanded .war file as well, but since we use Spring's Log4JConfigListener it wouldn't run from an unexploded .war file. Tomcat doesn't explode .war files put outside appBase (webapps) folder.
b) This approach doesn't prevent you from having context.xml in /usr/local/MyApp/META-INF/context.xml since it will not be used by Tomcat in this configuration. You can use it in your dev environment, where you dump your .war file into the appBase (webapps) folder.
This is what I've got so far, still looking out for better solutions.
这就是我们如何从 .WAR 文件中外部化 webapp 上下文
例如,我有一个名为 VirtualWebApp 的网络应用程序。
我将使用以下上下文定义创建类似 VirtualWebApp.xml 的文件:
要访问这些环境变量,您必须编写以下代码(只需查找):
This is how we can manage to externalize webapp context from .WAR File
For e.g. I have an webapp called VirtualWebApp.
I will create file like VirtualWebApp.xml with below context definition :
To access these environment variables you have to write below code(Just lookup) :
参考Apache Tomcat 5.5文档:
您可以轻松尝试这种方法,它可能会起作用,但我不确定这是否是一个好的解决方案,特别是如果您在 Tomcat 上运行多个 Web 应用程序。
By referring to Apache Tomcat 5.5 Documentation:
You could easily try this approach, it might work, but I'm not sure if this is a good solution especially if you are running multiple webapps on Tomcat.
我不知道如何修改 Tomcat 的行为,但我可以想到两种不同的解决方案:
env
的参数,并根据在构建过程中,它会将环境特定的context.xml
放置在您的 WAR 中。install
脚本,首先重新部署 WAR 文件(将其放置在webapps
目录中),然后根据环境对 Tomcat 安装进行修改,例如不同的主机名context.xml
中的 JDBC 数据源。我大量使用后一种方法,因为它适用于企业环境。职责分离策略通常会禁止开发团队了解生产数据库密码等信息。选项 #2 解决了此问题,因为只有 IT 操作人员才能在创建特定于环境的安装脚本后访问它们。
I don't know how to modify Tomcat's behaviour but I could think of 2 different solutions:
env
to your build scripts and depending on the value it places the environment specificcontext.xml
in your WAR during build.install
script for each environment that first redeploys the WAR file (places it inwebapps
directory) and then makes modifications to the Tomcat installation depending on environment, e.g. different hostname for JDBC DataSource incontext.xml
.I make heavy use of the latter approach as it works in enterprise environments. Separation of duties policies often prohibit the dev team from knowing e.g. production database passwords. Option #2 solves this problem because only IT operations have access to the environment specific install scripts after they have been created.
@n0rm1e:不确定 tomcat 是否为您的问题提供任何解决方案。但一种可能的解决方案是:-
通过以下步骤创建 ant 脚本:
i) 检查 [engine-name]/[server-name] 目录中是否存在 .xml 文件。如果存在,请备份/重命名。
ii) 将您的 war 文件复制到 tomcat webapps。重新启动 tomcat 服务器。
iii) 将备份的配置文件复制回 [engine-name]/[server-name] 目录
@n0rm1e: not sure if tomcat provides any sort of solution for you problem. But one possible solution can be:-
create an ant script with following steps:
i) Check existence of .xml file in [engine-name]/[server-name] directory. If it exists, take a back up of this/rename it.
ii) copy your war file to tomcat webapps. Restart tomcat server.
iii) copy backup-ed configuration file back to [engine-name]/[server-name] directory