【问题标题】:Add properties to property placeholder将属性添加到属性占位符
【发布时间】:2011-09-17 06:20:03
【问题描述】:

我有一个应用程序,其中属性占位符用于读取属性,在applicationContext.xml 中配置:

...
<context:property-placeholder
     location="classpath*:META-INF/spring/*.properties"/> 
...

应用程序在 Tomcat 中运行并使用 context.xml 中定义的参数。 应用程序像普通属性一样访问此参数 (@Value(${cfma.applicationUrl}))。 这行得通

在我的测试用例中,我没有这个 tomcat 属性,所以我想将它们“手动”添加到应用程序上下文中。但也可以正常加载applicationContext.xml

testContext.xml:

<import resource="classpath:/META-INF/spring/applicationContext.xml" />
<context:property-placeholder properties-ref="simulatedTomcatProperties"/>
<util:properties id="simulatedTomcatProperties">
   <prop key="cfmt.applicationBaseUrl">localhost:8080/cfmt</prop>
</util:properties>

现在我有两个上下文:property-placeholder,这不起作用(当然) - 所以我的问题是,我可以在我的测试中扩展“正常”属性占位符中的属性吗?强>


我需要的更多解释:

  • 生产环境(以及开发环境)通过 Tomcat 参数定义了一些属性。因此它们不包含在任何属性文件中,但可以像普通属性一样轻松访问它们 (@Value(${cfma.applicationUrl}))。而且不能有任何Fallback,如果Tomcat中没有定义属性,应用程序一定不能启动!
  • 在测试用例(使用 spring 上下文)中,我必须了解如何插入属性 (cfma.applicationUrl),以便可以将其注入带注释的变量中。 但是,如果我添加第二个 context:property-placeholder,它们不会合并:

@查看https://jira.springsource.org/browse/SPR-4881 上的评论——他们解释了这种行为。


当我谈论 Tomcat 参数时,我是在谈论这样的想法:

context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <Parameter name="cfmt.applicationBaseUrl"
          value="http://localhost/demoApp" override="false"/>
</Context>

【问题讨论】:

  • stackoverflow.com/questions/6375016/… 它有效地允许您定义多个属性位置。忽略缺少的属性文件,并加载列出的最后一个有效文件。
  • @Filip:我的问题与多个位置无关。我被多个属性占位符配置器困住了。我正在寻找一种方法来从我的 test-context.xml 扩展/更改“普通”应用程序上下文属性占位符配置器的配置
  • 对不起。我的评论不是很清楚,我不是在建议一种指定多个属性文件的方法,而是一种进行条件属性查找的方法。扩展答案如下。

标签: java unit-testing spring properties


【解决方案1】:

不确定这是否会有所帮助,但我在类似情况下所做的是拥有 2 个同名的 app.properties 文件,一个在 sec/test/resources 中,另一个在 src/main/resources 中。现在在测试期间加载第一个,因为测试类首先在类路径上,但是当我部署时只有主类在那里,所以它被加载了。

【讨论】:

  • 因为我的问题属于其他属性,所以我的解决方法是在 test/resources(Maven 基础项目)中为我的测试提供一个额外的属性文件。
  • 是的,我确实在两个文件中复制了属性!
【解决方案2】:

如果您将相同的location 属性添加到testContext.xml 中定义的context:property-placeholder 中,它是否可以工作?您还需要添加属性local-override="true" 以使properties-ref 覆盖META-INF 下的属性。

编辑:

鉴于您最近的评论,我认为您需要放弃使用 context 命名空间并直接使用在幕后使用的 Spring 对象。也许是这样的:

在applicationContext.xml中:

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath*:META-INF/spring/*.properties" />
</bean>

在 testContext.xml 中:

<bean id="propertyConfigurerTest" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" parent="propertyConfigurer">
    <property name="properties" ref="simulatedTomcatProperties" />
    <property name="localOverride" value="true" />
</bean>
<util:properties id="simulatedTomcatProperties">
   <prop key="cfmt.applicationBaseUrl">localhost:8080/cfmt</prop>
</util:properties>

我猜你希望本地属性覆盖从类路径资源定义的属性,所以我将 localOverride 定义为 true。

【讨论】:

  • 不,不幸的是,这没有帮助。据我了解,问题是如果我有两个 context:property-placeholder 定义,我还必须拥有占位符,并且没有合并。
  • 我希望testContext.xml 中的那个会覆盖applicationContext.xml 中的那个,如果它被第二次加载的话。您看到的错误行为是什么?
  • 不是不正确的,它是预期的(它不适用于两个上下文:property-placeholder)。行为是,注释为 @Value(${cfma.applicationUrl}) 的字段未在测试中填充。 -- 我正在寻找一种方法来从我的 testContext.xml 中的 applicationContext.xml 中“扩展”属性占位符。
【解决方案3】:

如果在您的主 applicationContext.xml 中,您使用 PropertiesFactoryBean 指定了如下所列的多个属性查找,则不会加载任何丢失的属性文件,并使用最后一次成功加载的属性文件。在您的情况下,将加载 default.properties (例如您的测试属性文件),并且由于不会加载第二个文件:${catalina}...,因此您的 @Value 字段将被注入默认指定的值。特性。

答案取自here

<bean id="myProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
   <property name="ignoreResourceNotFound" value="true" />
   <property name="locations">
      <list>
        <value>classpath:default.properties</value>
        <value>file:${catalina.home}/webapps/myProperties.properties</value>
      </list>
   </property>
</bean> 

【讨论】:

  • 所以你的建议和&lt;context:property-placeholder location="classpath*:META-INF/spring/*.properties"/&gt; 的区别并没有那么大。 - 至少你建议为测试添加一个额外的属性文件 - 对吧?
  • 没错。您还可以扩展 PropertiesFactoryBean 以更符合您的需求;我使用它来帮助我加载不同的配置文件,具体取决于我在做什么(例如,使用 JNDI 进行查找,或使用本地 H2 数据库,使用 DBUnit 播种等......)
【解决方案4】:

我通过将applicationContext.xml 拆分为两个文件解决了这个问题: - applicationContext.xml -- 包含“普通”bean,但不包含 applicationContext-properties.xml - applicationContext-properties.xml -- 包含属性占位符配置

applicationContext-properties.xml:

 <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
      <property name="locations" value="classpath*:META-INF/spring/*.properties" />
      <property name="ignoreUnresolvablePlaceholders" value="false" />
 </bean>

Web 应用程序在启动时加载这两个文件:

web.xml:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>

对于我的测试,我添加了一个属性文件:simulatedTomcat.test-properties,其中包含所有 tomcat 属性。 注意:此文件与 applicationContext-properties.xml 的属性占位符配置器使用的模式不匹配

然后我有一个用于我的测试的属性占位符配置器,它加载两种操作属性文件(*.properties*.test-properties

test-context.xml

<import resource="classpath:/META-INF/spring/applicationContext.xml" />
<bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer">
   <property name="locations">
      <list>
         <value>classpath*:META-INF/spring/*.properties</value>
         <value>classpath*:META-INF/spring/*.test-properties</value>
      </list>
   </property>
</bean>

【讨论】:

    猜你喜欢
    • 2015-11-05
    • 2016-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-02
    • 1970-01-01
    • 2021-07-27
    • 2012-01-19
    相关资源
    最近更新 更多