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

2024-10-28 08:37:00
admin
原创
73
摘要:问题描述:我在 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
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用