我正在开发两个Spring Boot应用程序,这些应用程序必须部署在现有的单个tomcat服务器上。其中一个(app1)应该在上下文路径 manager 中运行。另一个(app2)应该在上下文 customer1 和 customer2
中运行两次Tomcat
+ manager (app1)
+ customer1 (app2 with configuration 1)
+ customer2 (app2 with configuration 2)
我想要一个具有这样配置的目录
/opt
+ configuration
+ manager
| + application.properties
+ customer1
| + application.properties
+ customer2
+ application.properties
正在配置的目录与上下文路径匹配,并且每个应用程序都从相应的(路径)文件加载其配置。
我做了一些研究,但没有找到任何相关答案。大多数建议都建议使用环境变量来直接修改配置属性或使用spring.config.location
环境变量来设置新的配置位置。但是,它会影响服务器上的所有应用程序。
在先前的应用程序中(无需启动),我使用以下XML配置:
<bean id="appPropertyConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:app.properties</value>
<value>file:/opt/myappconfig/app.properties</value>
<value>file:${catalina.base}/my_app_config/conf.default.properties</value>
<value>file:${catalina.base}/my_app_config/conf/#{servletContext.contextPath != '' ? servletContext.contextPath : 'ROOT'}.properties</value>
</list>
</property>
</bean>
基本上从上到下依次选择一个属性并读取配置。路径中的一个:${catalina.base}/my_app_config/conf/*context_path*.properties
总是赢。
我正在尝试在Java配置的Spring Boot中实现相同的目标。到目前为止,我发现的最佳解决方案是使用自定义@PropertySource
进行配置:
@PropertySource(//
value = { //
"classpath:user-defaults.properties", //
"file:${my_app_config}/manager/application.properties", //
// This line is silently ignored even 'ignoreResourceNotFound = false'. The servletContext is probably null
"file:${my_app_config}/#{servletContext.contextPath != '' ? servletContext.contextPath : 'ROOT'}/application.properties"//
}, //
ignoreResourceNotFound = false//
)
@Configuration
public class PropertyConfig implements ApplicationContextAware {
/** PropertySourcesPlaceholderConfigurer has to be registered in order to resolve ${} place-holders. */
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
return pspc;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// Here I can't get the servlet context. This method get called much later then
ServletContext servletContext = applicationContext.getBean(ServletContext.class);
System.out.println("Servlet context is" + servletContext.getContextPath());
}
}
它有三个缺点。
#{servletContext …}
(可能)为null,整个末尾
@PropertySource
中的值将被忽略。现在也来不及
ServletContext
中的ApplicationContext
。的
PropertySourcesPlaceholderConfigurer
是更早创建的。user-defaults.properties
中定义所有可重写属性。
application.properties
中的值始终覆盖值形式
spring documentation的财产来源。我也试图像这样向propertyPlaceholderConfigurer
注入上下文路径
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer(@Value("#{servletContext.contextPath}") String contextPath) {
System.out.println(contextPath);
final PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
return pspc;
}
在How to use servlet contextPath with PropertySource?中建议,但我只有
Unsatisfied dependency expressed through method 'properties' parameter 0;
nested exception is org.springframework.beans.factory.BeanExpressionException:
Expression parsing failed; nested exception is
org.springframework.expression.spel.SpelEvaluationException:
EL1008E: Property or field 'servletContext' cannot be found on object of type
'org.springframework.beans.factory.config.BeanExpressionContext' -
maybe not public or not valid?
有人在不考虑servletContextPath的情况下如何加载外部配置吗?