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
Externalizing Tomcat webapp config from .war file
提问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.war
is 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 myHost
and your app is a war file named myApp.war
in the webapps
directory, then you could create tomcat/conf/Catalina/myHost/myApp.xml
with this content:
例如,如果您的主机已命名myHost
并且您的应用程序是myApp.war
在webapps
目录中命名的 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 .properties
files 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.ServletContextListener
which my be inconvenient
- JNDI - 为什么在程序配置而不是初始化期间构建复杂对象?
- 系统属性 - 您不能在单个 Tomcat 中单独配置相同 WAR 的多个实例
- 上下文参数 - 它们只能在 中访问
javax.servlet.Filter
,javax.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
-最好- 完全退出应用程序并自动扫描更改!!!
Context
can hold custom Loader
org.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
可以保存自定义Loader
org.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:
也可以看看:
- Adding a directory to tomcat classpath
- Can I create a custom classpath on a per application basis in Tomcat
- How to read a properties file outside my webapp context in Tomcat
- Configure Tomcat to use properties file to load DB connection information
- Should you set up database connection properties in server.xml or context.xml
- Externalize Tomcat configuration
- 将目录添加到 tomcat 类路径
- 我可以在 Tomcat 中为每个应用程序创建自定义类路径吗
- 如何在 Tomcat 中读取我的 webapp 上下文之外的属性文件
- 配置Tomcat使用properties文件加载DB连接信息
- 您是否应该在 server.xml 或 context.xml 中设置数据库连接属性
- 外化Tomcat配置
NOTEWith extending classpath to live directory you also allowed to externilize any other configs, like logging, auth, atc. I externilize logback.xml
in 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.bat
or setenv.sh
script in the bin
folder of tomcat. Set the classpath
variable like
我刚刚在tomcat的文件夹中添加了一个setenv.bat
或setenv.sh
脚本bin
。classpath
像这样设置变量
set CLASSPATH=my-propery-folder