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

时间:2012-12-19 16:21:02

标签: linux tomcat configuration

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

我听说有一种方法可以使用tomcat/conf/Catalina/myApp中的替换配置文件来完成此操作。这是我无法搞清楚的方法。

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

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

4 个答案:

答案 0 :(得分:63)

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

Tomcat网站上有configuring a context的好文档。有关如何创建文件以及放置文件的详细信息,请参阅Defining a Context section

例如,如果您的主机名为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>

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

答案 1 :(得分:43)

我喜欢.properties个文件而不是

  • JNDI - 为什么在程序配置期间构建复杂对象而不是初始化时间?
  • 系统属性 - 您无法在单个Tomcat中单独配置多个相同WAR的实例
  • 上下文参数 - 只能在javax.servlet.Filterjavax.servlet.ServletContextListener中访问,我不方便

Tomcat 7 Context持有Loader元素。根据{{​​3}}部署描述符(<Context>标记中的内容)可以放在:

  • $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可以保留自定义Loader docs(在现代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>

如果您使用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>

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

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

而不是JNDI:

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

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

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

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

另见:

注意通过将类路径扩展到实时目录,您还允许外部化任何其他配置,例如logging,auth,atc。我以这种方式对logback.xml进行了外部化。

更新 Externalize Tomcat configuration <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>

答案 2 :(得分:1)

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

答案 3 :(得分:0)

我刚刚在tomcat的setenv.sh文件夹中添加了binclasspath脚本。将set CLASSPATH=my-propery-folder 变量设置为

<ReactTable
    data={ tableData }
    columns={ tableColumns }
    showPagination={ false }
    defaultPageSize={ tableData.length }
/>