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

2024-10-28 08:37:00
admin
原创
99
摘要:问题描述:我在 Tomcat 7 中配置 webapp 时遇到了麻烦。在我的 WAR 文件中,有一个属性文件myApp/WEB-INF/classes/myProps.props,其中包含特定于环境的属性。我试图在服务器上覆盖该配置文件,以便将同一个 WAR 文件部署到多个环境。我听说有一种方法可以使用替换配...

问题描述:

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

我听说有一种方法可以使用替换配置文件来实现这一点tomcat/conf/Catalina/myApp。这是我很难弄清楚的方法。

此外,myApp.war它是运行在同一 Tomcat 服务器上的众多应用程序之一,并且不以本地主机身份运行。我希望能够为多个 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

解决方案 1:

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

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

举例来说,如果你的主机名为 name ,而你的应用程序是目录中myHost名为 name 的 war 文件,那么你可以使用如下内容创建:myApp.war`webapps`tomcat/conf/Catalina/myHost/myApp.xml

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

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

解决方案 2:

我喜欢.properties文件而不是

  • JNDI - 为什么在程序配置期间而不是初始化时构建复杂的对象?

  • 系统属性 - 您不能在单个 Tomcat 中分别配置同一个 WAR 的多个实例

  • 上下文参数 - 它们只能在 中访问javax.servlet.Filterjavax.servlet.ServletContextListener这可能会不方便

Tomcat 7上下文包含Loader元素。根据文档,部署描述符(<Context>标签中的 what)可以放置在:

  • $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 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>

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

参见:

  • 将目录添加到 tomcat 类路径

  • 我可以在 Tomcat 中根据每个应用程序创建自定义类路径吗

  • 如何在 Tomcat 中读取我的 webapp 上下文之外的属性文件

  • 配置 Tomcat 使用属性文件加载 DB 连接信息

  • 您是否应该在 server.xml 或 context.xml 中设置数据库连接属性

  • 外部化 Tomcat 配置

注意:通过将类路径扩展到实时目录,您还可以将任何其他配置(如日志记录、身份验证、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>

解决方案 3:

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

解决方案 4:

我刚刚在tomcat 文件夹中添加了一个setenv.batsetenv.sh脚本。设置变量如下bin`classpath`

set CLASSPATH=my-propery-folder
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   681  
  在项目管理领域,集成产品开发(IPD)流程以其高效、协同的特点,被众多企业视为提升产品竞争力的关键。IPD流程强调跨部门、跨职能的紧密合作,以确保产品从概念到市场各个环节的无缝衔接。然而,实现这一目标并非易事,它需要企业深刻理解并掌握IPD流程中的跨部门协作艺术。本文将深入探讨IPD流程中跨部门协作的三个关键点,旨在为...
IPD项目管理咨询   9  
  掌握IPD流程图:提升团队协作的关键路径在当今快速变化的商业环境中,团队协作的效率与效果直接关系到项目的成功与否。集成产品开发(Integrated Product Development,简称IPD)作为一种先进的研发管理理念,通过跨部门、跨领域的协同工作,能够显著提升产品开发的速度与质量。而IPD流程图,则是这一理...
IPD流程阶段   9  
  IPD流程概述:理解其核心价值与实施背景集成产品开发(Integrated Product Development,简称IPD)是一种先进的产品开发管理理念,它强调跨部门协作、市场导向和快速响应变化的能力。IPD流程不仅关注产品本身的技术创新,更注重将市场、研发、生产、销售等各个环节紧密集成,以实现产品从概念到市场的高...
华为IPD是什么   7  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程以其跨部门协作、高效决策和快速响应市场变化的特点,被众多企业视为提升竞争力的关键。然而,实践IPD流程并非易事,项目管理中的种种错误往往阻碍了其效果的充分发挥。本文旨在深入探讨如何在实施IPD流程时避免这些常见错误,...
IPD框架   7  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用