在 Tomcat 中将配置与 WAR 分开的优雅方法

2022-09-02 10:44:24

我试图找到在Tomcat中运行的Spring Web应用程序中传递复杂配置的最佳方法。目前,我使用 JNDI 将数据源和字符串从 Tomcat 上下文传递到 web 应用程序,这很有效。

但是,假设我需要选择通知服务的实现。Spring无法有条件地选择要实例化的bean(尽管在过去,我使用JNDI字符串通过设置上下文ConfigLocation来导入bean的预定义配置)。

我还看到许多Web应用程序提供配置工具,该工具将创建自定义WAR文件。在我看来,这是不好的形式,如果没有其他原因,因为它可以防止从上游重新部署WAR,而无需进行许多检查以确保所有配置都已重新应用。

理想情况下,我将能够提供一个Spring XML文件,该文件存在于Web应用程序之外的文件系统上。但是,spring import 指令似乎没有解决 ${} 变量,因此无法提供自定义。

我是否可以在此处采用任何技术来正确分离复杂配置与 Web 应用?


答案 1

如果我有一组要配置的特定bean,并且此配置必须与WAR文件分开,我通常会执行以下操作:

applicationContext 中.xml

<!-- here you have a configurer based on a *.properties file -->
<bean id="configurer" 
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="file://${configDir}/configuration.properties"/>
    <property name="ignoreResourceNotFound" value="false" />
    <property name="ignoreUnresolvablePlaceholders" value="false" />
    <property name="searchSystemEnvironment" value="false" />
</bean>

<!-- this is how you can use configuration properties -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="host" value="${smtp.host}"/>
</bean>

配置属性中

smtp.host=smtp.your-isp.com

您还需要使用 -DconfigDir=/path/to/configuration/directory 启动 Tomcat


答案 2

如果您使用的是Spring 3,则可以利用Spring表达式语言。假设您有两个应用程序 app1.war 和 app2.war,它们需要一个名为 config.properties 的属性文件。应用程序将使用上下文路径 /app1 和 /app2 进行部署。

在公共目录中创建两个目录app1和app2,例如。C:\myConfig\app1 和 C:\myConfig\app2。

将 config.properties 放在 app1 中,将另一个 config.properties 放在 app2 中。

然后创建一个文件 ${CATALINA_HOME}/conf/[enginename]/[hostname]/context.xml.default,内容如下:

上下文.xml.default:

<Context>
  <Parameter name="myConfigDirectory" value="C:/myConfig" override="false"/>
</Context>

参数 myConfigDirectory 将可用于主机上的所有应用程序。最好在上下文.xml.default 中创建此参数,而不是在服务器.xml中创建此参数,因为以后无需重新启动 tomcat 即可更改该文件。

在应用程序中Context.xml war中,您可以使用SpEL表达式访问config.properties:“#{contextParameters.myConfigDirectory + servletContext.contextPath}/config.properties”,因此例如,您可以编写:

应用上下文.xml:

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="location" value="file:#{contextParameters.myConfigDirectory + servletContext.contextPath}/config.properties" />
</bean>

对于具有 contextPath /app1 的应用程序,表达式将扩展为 C:/myConfig/app1,对于具有 contextPath /app2 的应用程序,表达式将扩展为 C:/myConfig/app2。这将使应用程序根据其上下文路径访问 config.properties 文件。


推荐