Linux 从 .war 文件外部化 Tomcat webapp 配置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13956651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 18:05:02  来源:igfitidea点击:

Externalizing Tomcat webapp config from .war file

linuxtomcatconfiguration

提问by mfa

I am having trouble with configuring a webapp in Tomcat 7. In my WAR file, there is a properties file myApp/WEB-INF/classes/myProps.props, and it contains environment-specific properites. I am trying to override that configuration file on the server, so that the same WAR file will deploy to multiple environments.

我在 Tomcat 7 中配置 webapp 时遇到问题。在我的 WAR 文件中,有一个属性文件myApp/WEB-INF/classes/myProps.props,它包含特定于环境的属性。我正在尝试覆盖服务器上的该配置文件,以便将相同的 WAR 文件部署到多个环境。

I heard there was a way to do this using replacement config files in tomcat/conf/Catalina/myApp. This is the method I am having trouble figuring out.

我听说有一种方法可以使用tomcat/conf/Catalina/myApp. 这是我无法弄清楚的方法。

Also, myApp.waris one of many running on the same Tomcat server, and it does not run as localhost. I want to be able to solve this problem for several of the webapps.

此外,它myApp.war是在同一台 Tomcat 服务器上运行的众多服务器之一,它不作为 localhost 运行。我希望能够为几个 webapps 解决这个问题。

Server version: Apache Tomcat/7.0.23
Server built:   Nov 20 2011 07:36:25
Server number:  7.0.23.0
OS Name:        Linux

采纳答案by Ryan Stewart

Your tomcat/conf/Catalina/<host>can contain context descriptors that let you configure lots of things including defining "environment entries", which are accessible from Java via JNDI. There are lots of ways to go about using it. Personally, I set an environment entry which is the file system path to my properties file. My app is built to check for this entry, and if it doesn't exist, look for the file on the classpath instead. That way, in dev, we have the dev properties right there on the classpath, but when we build and deploy, we point it to an external file.

tomcat/conf/Catalina/<host>可以包含上下文描述符,让您可以配置许多内容,包括定义“环境条目”,这些内容可以通过 JNDI 从 Java 访问。有很多方法可以使用它。就个人而言,我设置了一个环境条目,它是我的属性文件的文件系统路径。我的应用程序旨在检查此条目,如果它不存在,则在类路径中查找该文件。这样,在 dev 中,我们在类路径上有 dev 属性,但是当我们构建和部署时,我们将它指向一个外部文件。

There's good documentation for configuring a contexton the Tomcat website. See the Defining a Contextsectionon details of how to create the file and where to put it.

Tomcat 网站上有关于配置上下文的很好的文档。有关如何创建文件及其放置位置的详细信息,请参阅定义上下文部分

As an example, if your host is named myHostand your app is a war file named myApp.warin the webappsdirectory, then you could create tomcat/conf/Catalina/myHost/myApp.xmlwith this content:

例如,如果您的主机已命名myHost并且您的应用程序是myApp.warwebapps目录中命名的 war 文件,那么您可以tomcat/conf/Catalina/myHost/myApp.xml使用以下内容创建:

<Context>
    <Environment name="configurationPath" value="/home/tomcat/myApp.properties" type="java.lang.String"/>
</Context>

Then from your code, you'd do a JNDI lookup on java:comp/env/configurationPath(95% certainty here) to get that string value.

然后从您的代码中,您将对java:comp/env/configurationPath(此处为 95% 的确定性)进行JNDI 查找以获取该字符串值。

回答by bmoc

You can try to place your configuration (properties file) in Apache Tomcat\lib in JAR file and remove it from the web application. When the Tomcat's class loader won't find your config in webapp it will try to find in "lib" directory. So you can externalize your configuration just moving the config to global lib dir (it's shared among other webapps).

您可以尝试将您的配置(属性文件)放在 JAR 文件中的 Apache Tomcat\lib 中,并将其从 Web 应用程序中删除。当 Tomcat 的类加载器在 webapp 中找不到您的配置时,它会尝试在“lib”目录中查找。因此,您可以将配置外部化,只需将配置移动到全局 lib 目录(它在其他 web 应用程序之间共享)。

回答by gavenkoa

I like .propertiesfiles instead of

我喜欢.properties文件而不是

  • JNDI - why build complex object during program configurationinstead of initialization time?
  • system properties - you can't separately configure several instances of same WAR in single Tomcat
  • context parameters - they accessible only in javax.servlet.Filter, javax.servlet.ServletContextListenerwhich my be inconvenient
  • JNDI - 为什么在程序配置而不是初始化期间构建复杂对象
  • 系统属性 - 您不能在单个 Tomcat 中单独配置相同 WAR 的多个实例
  • 上下文参数 - 它们只能在 中访问javax.servlet.Filterjavax.servlet.ServletContextListener这很不方便

Tomcat 7 Contexthold Loaderelement. According to docsdeployment descriptor (what in <Context>tag) can be placed in:

Tomcat 7 Context持有Loader元素。根据文档部署描述符(<Context>标签中的内容)可以放置在:

  • $CATALINA_BASE/conf/server.xml- bad - require server restarts in order to reread config
  • $CATALINA_BASE/conf/context.xml- bad - shared across all applications
  • $CATALINA_BASE/work/$APP.war:/META-INF/context.xml- bad - require repackaging in order to change config
  • $CATALINA_BASE/work/[enginename]/[hostname]/$APP/META-INF/context.xml- nice, but see last option!!
  • $CATALINA_BASE/webapps/$APP/META-INF/context.xml- nice, but see last option!!
  • $CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml- best- completely out of application and automatically scanned for changes!!!
  • $CATALINA_BASE/conf/server.xml- 不好 - 需要重新启动服务器才能重新读取配置
  • $CATALINA_BASE/conf/context.xml- 不好 - 在所有应用程序享
  • $CATALINA_BASE/work/$APP.war:/META-INF/context.xml- 不好 - 需要重新打包才能更改配置
  • $CATALINA_BASE/work/[enginename]/[hostname]/$APP/META-INF/context.xml-不错,但请参阅最后一个选项!!
  • $CATALINA_BASE/webapps/$APP/META-INF/context.xml-不错,但请参阅最后一个选项!!
  • $CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml-最好- 完全退出应用程序并自动扫描更改!!!

Contextcan hold custom Loaderorg.apache.catalina.loader.VirtualWebappLoader(available in modern Tomcat 7, you can add own separate classpathto your .properties), and Parameter(accessed via FilterConfig.getServletContext().getInitParameter(name)) and Environment(accessed via new InitialContext().lookup("java:comp/env").lookup("name")):

Context可以保存自定义Loaderorg.apache.catalina.loader.VirtualWebappLoader(在现代 Tomcat 7 中可用,您可以将自己单独的类路径添加到您的.properties),和Parameter(通过访问FilterConfig.getServletContext().getInitParameter(name))和Environment(通过访问new InitialContext().lookup("java:comp/env").lookup("name")):

<Context docBase="${basedir}/src/main/webapp"
         reloadable="true">
    <!-- http://tomcat.apache.org/tomcat-7.0-doc/config/context.html -->
    <Resources className="org.apache.naming.resources.VirtualDirContext"
               extraResourcePaths="/WEB-INF/classes=${basedir}/target/classes,/WEB-INF/lib=${basedir}/target/${project.build.finalName}/WEB-INF/lib"/>
    <Loader className="org.apache.catalina.loader.VirtualWebappLoader"
            virtualClasspath="${basedir}/target/classes;${basedir}/target/${project.build.finalName}/WEB-INF/lib"/>
    <JarScanner scanAllDirectories="true"/>

    <Parameter name="min" value="dev"/>
    <Environment name="app.devel.ldap" value="USER" type="java.lang.String" override="true"/>
    <Environment name="app.devel.permitAll" value="true" type="java.lang.String" override="true"/>
</Context>

If you use Spring and it's XML config:

如果您使用 Spring 并且它是 XML 配置:

<context:property-placeholder location="classpath:app.properties"/>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
    <property name="url" value="jdbc:oracle:thin:@${db.host}:${db.port}:${db.user}"/>
    <property name="username" value="${db.user}"/>
    <property name="password" value="${db.pass}"/>
</bean>

With Spring injecting above properties into bean fields are easy:

使用 Spring 将上述属性注入 bean 字段很容易:

@Value("${db.user}") String defaultSchema;

instead of JNDI:

而不是 JNDI:

@Inject ApplicationContext context;
Enviroment env = context.getEnvironment();
String defaultSchema = env.getProperty("db.user");

Note also that EL allow this (default values and deep recursive substitution):

另请注意,EL 允许这样做(默认值和深度递归替换):

@Value('${db.user:testdb}') private String dbUserName;

<property name='username' value='${db.user.${env}}'/>

See also:

也可以看看:

NOTEWith extending classpath to live directory you also allowed to externilize any other configs, like logging, auth, atc. I externilize logback.xmlin such way.

注意通过将类路径扩展到活动目录,您还允许外部化任何其他配置,如日志记录、身份验证、atc。我logback.xml以这种方式外化。

UPDATETomcat 8 change syntax for<Resources>and <Loader>elements, corresponding part now look like:

更新Tomcat 8 更改<Resources><Loader>元素的语法,对应部分现在如下所示:

<Resources>
    <PostResources className="org.apache.catalina.webresources.DirResourceSet"
                   webAppMount="/WEB-INF/classes" base="${basedir}/target/classes" />
    <PostResources className="org.apache.catalina.webresources.DirResourceSet"
                   webAppMount="/WEB-INF/lib" base="${basedir}/target/${project.build.finalName}/WEB-INF/lib" />
</Resources>

回答by baliman

I just added a setenv.bator setenv.shscript in the binfolder of tomcat. Set the classpathvariable like

我刚刚在tomcat的文件夹中添加了一个setenv.batsetenv.sh脚本binclasspath像这样设置变量

set CLASSPATH=my-propery-folder