【问题标题】:PropertyPlaceholderConfigurer and environment variables in .properties files.properties 文件中的 PropertyPlaceholderConfigurer 和环境变量
【发布时间】:2012-05-06 16:06:28
【问题描述】:

我有一个带有 PropertyPlaceholderConfigurer 的 Spring application-context.xml,可以从 .properties 文件中获取属性值。主要和测试源文件夹具有单独的 .properties 文件。问题是我需要在 .properties 文件中使用环境变量。但是当我按照以下方式进行操作时:

property.name=${env.SYSTEM_PROPERTY}

我收到以下错误:

org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'beanName' defined in class path resource [com/example/applicationContext.xml]: Could not resolve placeholder 'env.SYSTEM_PROPERTY'

而占位符配置器定义为

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:com/example/application.properties"/>
</bean>

任何想法如何使 property.name 被解释为环境变量(而不是占位符)?

最好的问候,德米特里。

【问题讨论】:

    标签: java spring environment-variables applicationcontext properties-file


    【解决方案1】:

    我使用了 benkiefer 的方法,但是我不得不在 web.xml 中添加一个监听器:

    <listener>
       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    

    【讨论】:

      【解决方案2】:

      使用:

      <context:property-placeholder location="classpath:env.properties"/>
      

      改变你的:

      property.name=${env.SYSTEM_PROPERTY}
      

      收件人:

      property.name=${SYSTEM_PROPERTY}
      

      我正在使用 Spring 3.0.4.RELEASE,但我不知道这是什么时候引入的。

      【讨论】:

      • 非常感谢。我已经使用帮助程序类解决了问题,该类查找 VM 属性,然后是环境变量,然后使用默认值。现在它对我来说更灵活。不过还是谢谢,下次我会试试你的方法。
      • 奇怪 - 使用 spring 3.0.4,这似乎不起作用
      【解决方案3】:

      我可能会彻底改变解决方案:直接注入系统属性,而不是注入引用系统属性的属性

      例如

      @Value("#{ systemProperties['JAVA_MY_ENV'] }") 
      private String myVar;
      

      <property name ="myVar" value="#{systemProperties['JAVA_MY_ENV']}"/>
      

      我使用这样的属性占位符配置器

      <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
          <list>
              <value>classpath:someprops.properties</value>
          </list>
        </property>
        <property name="ignoreResourceNotFound" value="true" />
        <property name="searchSystemEnvironment" value="true" />
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
      

      您还必须记住使用

      将参数传递到程序中
       -DJAVA_MY_ENV=xyz
      

      这样,当您运行生产版本时,您可以传递一件事,而在运行测试时传递另一件事。

      我经常做的事情是这样的:

        <property name="locations">
          <list>
            <value>classpath:someprops.properties</value>
            <value>classpath:someprops-{environment}.properties</value>
          </list>
        </property>
      

      其中环境是 prod/stage/test/int/ci/local(每个环境 1 个 - 您现在可能只有 2 或 3 个)。您可以将环境变量传递给程序。无论其在本地 pc/tests 上的生产/运行是否在 someprops.properties 属性文件中,任何属性都应该相同。任何特定于环境/运行方式的文件都将放入更具体的文件中(您应该将其放入 someprops.properties 文件以及默认值,除非被覆盖机制)

      例如 在类路径中:someprops.properties

      url=www.mysite.com
      

      在类路径中:someprops-local.properties

      url=localhost
      

      通过使用这个基本思想,您可以以干净的方式将测试和程序的正常运行属性分开。

      【讨论】:

      • 这很好。然而,一个问题是忘记定义运行时变量会产生棘手的运行时错误,例如找不到 config_xxx 文件等。为了改善这种情况,我注册了一个实现特殊 spring 接口的 bean,如下所示: class EnvironmentReporter implements PriorityOrdered, BeanFactoryPostProcessor, EnvironmentAware {...} environment.getProperty 允许我检查预期的属性并在创建任何其他 bean 之前彻底失败.
      猜你喜欢
      • 2012-02-13
      • 2016-02-08
      • 2018-07-04
      • 1970-01-01
      • 2016-10-17
      • 1970-01-01
      • 2017-03-06
      • 2011-06-11
      • 2016-11-13
      相关资源
      最近更新 更多