从 .war 文件外部化 Tomcat webapp 配置
- 2024-10-28 08:37:00
- admin 原创
- 73
问题描述:
我在 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.Filter
,javax.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.bat
或setenv.sh
脚本。设置变量如下bin
`classpath`
set CLASSPATH=my-propery-folder
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件