从.war文件中外部化Tomcat webappconfiguration
我在configurationTomcat 7中的webapp时遇到了麻烦。在我的war文件中,有一个属性文件myApp / WEB-INF / classes / myProps.props,它包含特定于环境的特性。 我试图覆盖服务器上的configuration文件,以便相同的战争文件将部署到多个环境。
我听说有一种方法可以在tomcat / conf / Catalina / myApp中使用replaceconfiguration文件。 这是我无法解决的方法。
而且,myApp.war是运行在同一个tomcat服务器上的许多程序之一,并且它不能作为localhost运行。 我想能够解决这个问题的几个Web应用程序。
Server version: Apache Tomcat/7.0.23 Server built: Nov 20 2011 07:36:25 Server number: 7.0.23.0 OS Name: Linux
你的tomcat/conf/Catalina/<host>
可以包含上下文描述符,可以让你configuration很多东西,包括定义“环境条目”,这些条目可以通过JNDI从Java访问。 有很多方法可以使用它。 就我个人而言,我设置了一个环境条目,这是我的属性文件的文件系统path。 我的应用程序是为检查此条目而构build的,如果它不存在,请在类path中查找该文件。 这样,在dev中,我们在classpath上有开发属性,但是当我们构build和部署时,我们将它指向一个外部文件。
在Tomcat网站上configuration上下文有很好的文档。 请参阅“定义上下文”一节,了解如何创build文件以及放置位置的详细信息。
例如,如果您的主机名为“myHost”,并且您的应用程序是webapps目录中名为“myApp.war”的war文件,那么您可以使用以下内容创buildtomcat/conf/Catalina/myHost/myApp.xml
:
<Context> <Environment name="configurationPath" value="/home/tomcat/myApp.properties" type="java.lang.String"/> </Context>
然后从你的代码中,你可以对java:comp/env/configurationPath
(这里95%的确定性)进行JNDI查找来获得该string值。
我喜欢.properties
文件,而不是
- JNDI – 为什么在程序configuration期间构build复杂对象而不是初始化时间?
- 系统属性 – 不能在单个Tomcat中单独configuration相同WAR的几个实例
- 上下文参数 – 它们只能在
javax.servlet.Filter
,javax.servlet.ServletContextListener
访问,我不方便
Tomcat 7 上下文保存Loader元素。 根据文档部署描述符( <Context>
标签中)可以放置在:
-
$CATALINA_BASE/conf/server.xml
– 坏 – 要求服务器重新启动,以重新configuration -
$CATALINA_BASE/conf/context.xml
– bad – 在所有应用程序中共享 -
$CATALINA_BASE/work/$APP.war:/META-INF/context.xml
– 坏 – 需要重新打包才能更改configuration -
$CATALINA_BASE/work/[enginename]/[hostname]/$APP/META-INF/context.xml
– 不错 ,但看到最后一个选项! -
$CATALINA_BASE/webapps/$APP/META-INF/context.xml
– 很好 ,但看到最后的select! -
$CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml
– 最好 – 完全不在应用程序中,并自动扫描更改!
Context
可以容纳自定义的Loader
org.apache.catalina.loader.VirtualWebappLoader (可以在现代Tomcat 7中使用,可以将自己的单独的类path添加到.properties
)和Parameter
(通过FilterConfig.getServletContext().getInitParameter(name)
Environment
(通过new InitialContext().lookup("java:comp/env").lookup("name")
访问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>
如果你使用Spring并且它是XMLconfiguration:
<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>
使用Spring将上面的属性注入bean域是很容易的:
@Value("${db.user}") String defaultSchema;
而不是JNDI:
@Inject ApplicationContext context; Enviroment env = context.getEnvironment(); String defaultSchema = env.getProperty("db.user");
还要注意EL允许这个(默认值和深度recursionreplace):
@Value('${db.user:testdb}') private String dbUserName; <property name='username' value='${db.user.${env}}'/>
也可以看看:
- 添加一个目录到tomcat classpath
- 我可以在Tomcat的每个应用程序基础上创build自定义类path吗?
- 如何在Tomcat的webapp上下文之外读取一个属性文件
- configurationTomcat以使用属性文件加载数据库连接信息
- 应该在server.xml还是context.xml中设置数据库连接属性
- 外部化Tomcatconfiguration
注意通过将类path扩展到活动目录,您还允许外部化任何其他configuration ,例如logging,auth,atc。 我以这种方式外部化logback.xml
。
更新 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>
您可以尝试将您的configuration(属性文件)放在Apache Tomcat \ lib中的JAR文件中,并将其从Web应用程序中删除。 当Tomcat的类加载器在webapp中找不到你的configuration时,它会尝试在“lib”目录中find。 所以你可以将configuration外部化,只需将configuration移动到全局库目录(它是在其他web应用程序之间共享的)。
我刚刚在tomcat的bin文件夹中添加了setenv.bat或setenv.sh脚本。 像设置CLASSPATH = my-propery-folder一样设置classpathvariables
约翰
- app.config文件和XYZ.settings文件有什么区别?
- Android onConfigurationChanged没有被调用
- 使用XML在app.config中包含或configuration引用来包含其他configuration文件的设置
- 更改连接string并在运行时重新加载app.config
- 如何在Tomcat上部署基于EJB的应用程序
- 用户的Subversionconfiguration文件在主要操作系统上存储在哪里?
- 一个类库的app.config
- 查询参数(postgresql.conf设置),如“max_connections”
- configurationlog4net根据级别向不同的appender发送错误