如何在Spring applicationContext中读取系统环境变量


116

如何在应用程序上下文中读取系统环境变量?

我想要类似的东西:

<util:properties id="dbProperties"
        location="classpath:config_DEV/db.properties" />

要么

<util:properties id="dbProperties"
        location="classpath:config_QA/db.properties" />

取决于环境。

我的应用程序上下文中可以有这样的东西吗?

<util:properties id="dbProperties"
        location="classpath:config_${systemProperties.env}/db.properties" />

根据系统环境变量设置实际值的地方

我正在使用Spring 3.0

Answers:



106

您接近:o)Spring 3.0添加了Spring Expression Language。您可以使用

<util:properties id="dbProperties" 
    location="classpath:config_#{systemProperties['env']}/db.properties" />

结合java ... -Denv=QA应该可以解决您的问题。

还请注意@yiling的评论:

为了访问系统环境变量(即amoe注释的OS级别变量),我们可以在该EL中仅使用“ systemEnvironment”代替“ systemProperties”。喜欢 #{systemEnvironment['ENV_VARIABLE_NAME']}


什么是Java ... -Denv = QA意味着什么?
fresh_dev 2012年

2
您设置一个Java系统属性值。您可以在代码中读取该值,例如assert System.getProperty("env") == "QA";
amra 2012年

我认为这个答案是不正确的,它不允许读取系统环境变量(即使用设置的OS级变量export,等等),仅允许读取Java系统属性。
amoe 2013年

2
-Dprop = ...在命令行中设置Java属性。您可以通过阅读此属性System.getProperty("prop")。如果您想读取OS属性,请使用System.getenv("os-env-variable")。参见javadoc:docs.oracle.com/javase/6/docs/api/java/lang/System.html
2014年

22
为了访问系统环境变量(即amoe注释的OS级别变量),我们可以在该EL中仅使用“ systemEnvironment”代替“ systemProperties”。像#{systemEnvironment['ENV_VARIABLE_NAME']}
伊陵2014年

51

现在你可以放

@Autowired
private Environment environment;

在你的@Component@Bean等等,然后通过访问属性Environment类:

environment.getProperty("myProp");

对于单一属性@Bean

@Value("${my.another.property:123}") // value after ':' is the default
Integer property;

另一种方法是方便的@ConfigurationProperties豆:

@ConfigurationProperties(prefix="my.properties.prefix")
public class MyProperties {
  // value from my.properties.prefix.myProperty will be bound to this variable
  String myProperty;

  // and this will even throw a startup exception if the property is not found
  @javax.validation.constraints.NotNull
  String myRequiredProperty;

  //getters
}

@Component
public class MyOtherBean {
  @Autowired
  MyProperties myProperties;
}

注意:只需记住在设置新的环境变量后重新启动eclipse


1
是否可以通过Environment接口访问env变量?
Nikhil Sahu

@NikhilSahu是的,他们是。您可以使用与查询时相同的键来访问它们,java.lang.System例如,要获取env.getProperty("os.name")假设env您的实例是OS类型org.springframework.core.env.Environment
Ninetou

1
@Autowired private Environment environment;不适用于我Component的环境始终为空
a_horse_with_no_name18年

26

是的,你可以 <property name="defaultLocale" value="#{ systemProperties['user.region']}"/>

变量systemProperties是预定义的,请参见6.4.1基于XML的配置


8

在您的bean定义中,确保包括“ searchSystemEnvironment”并将其设置为“ true”。如果使用它来构建文件的路径,请将其指定为file:/// url。

因此,例如,如果您有一个配置文件位于

/testapp/config/my.app.config.properties

然后像这样设置环境变量:

MY_ENV_VAR_PATH=/testapp/config

并且您的应用可以使用如下所示的Bean定义加载文件:

例如

<bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer">
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="searchSystemEnvironment" value="true" />
    <property name="searchContextAttributes" value="true" />
    <property name="contextOverride" value="true" />
    <property name="ignoreResourceNotFound" value="true" />
    <property name="locations">
        <list>
            <value>file:///${MY_ENV_VAR_PATH}/my.app.config.properties</value>
        </list>
    </property>
</bean>

8

使用Spring EL可以编写以下示例

<bean id="myBean" class="path.to.my.BeanClass">
    <!-- can be overridden with -Dtest.target.host=http://whatever.com -->
    <constructor-arg value="#{systemProperties['test.target.host'] ?: 'http://localhost:18888'}"/>
</bean>

5

对于我的用例,我只需要访问系统属性,但要提供未定义的默认值。

这是您的操作方式:

<bean id="propertyPlaceholderConfigurer"   
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="searchSystemEnvironment" value="true" />
</bean>  
<bean id="myBean" class="path.to.my.BeanClass">
    <!-- can be overridden with -Dtest.target.host=http://whatever.com -->
    <constructor-arg value="${test.target.host:http://localhost:18888}"/>
</bean>

4

声明财产占位符如下

<bean id="propertyPlaceholderConfigurer"   
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="locations">
        <list>
            <value>file:///path.to.your.app.config.properties</value>
        </list>
    </property>
</bean>

然后,假设您要读取System.property("java.io.tmpdir")Tomcat bean或任何bean,然后在属性文件中添加以下内容:

tomcat.tmp.dir=${java.io.tmpdir}

1

这是您的操作方式:

<bean id="systemPrereqs" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" scope="prototype">
             <property name="targetObject" value="#{@systemProperties}" />
             <property name="targetMethod" value="putAll" />
             <property name="arguments">
                   <util:properties>
                       <prop key="deployment.env">dev</prop>
                   </util:properties>
            </property>
    </bean>

但是请记住,首先加载spring,然后它将加载此bean MethodInvokingFactoryBean。因此,如果您要在测试用例中使用它,请确保使用依赖。例如在这种情况下

如果您将其用于主类,最好将pom.xml设置为

<systemProperty>
    <name>deployment.env</name>
    <value>dev</value>
</systemProperty>

1

您可以在属性文件中提及变量属性,并定义特定于环境的属性文件,例如local.properties,production.propertied等。

现在基于环境,可以在启动时调用的侦听器之一(例如ServletContextListener)中读取其中一个属性文件。

该属性文件将包含各种键的特定于环境的值。

样本“ local.properties”

db.logsDataSource.url=jdbc:mysql://localhost:3306/logs
db.logsDataSource.username=root
db.logsDataSource.password=root

db.dataSource.url=jdbc:mysql://localhost:3306/main
db.dataSource.username=root
db.dataSource.password=root

样本“ production.properties”

db.logsDataSource.url=jdbc:mariadb://111.111.111.111:3306/logs
db.logsDataSource.username=admin
db.logsDataSource.password=xyzqer

db.dataSource.url=jdbc:mysql://111.111.111.111:3306/carsinfo
db.dataSource.username=admin
db.dataSource.password=safasf@mn

要使用这些属性文件,可以使用如下所述的REsource

        PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
        ResourceLoader resourceLoader = new DefaultResourceLoader();

        Resource resource = resourceLoader.getResource("classpath:"+System.getenv("SERVER_TYPE")+"DB.properties");
        configurer.setLocation(resource);
        configurer.postProcessBeanFactory(beanFactory);

可以将SERVER_TYPE定义为具有适用于本地和生产环境的值的环境变量。

通过这些更改,appplicationContext.xml将进行以下更改

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
 <property name="driverClassName" value="com.mysql.jdbc.Driver" />
  <property name="url" value="${db.dataSource.url}" />
  <property name="username" value="${db.dataSource.username}" />
  <property name="password" value="${db.dataSource.password}" />

希望这可以帮助 。


1

感谢@Yiling。那是一个提示。

<bean id="propertyConfigurer"
        class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer">

    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="searchSystemEnvironment" value="true" />
    <property name="locations">
        <list>
            <value>file:#{systemEnvironment['FILE_PATH']}/first.properties</value>
            <value>file:#{systemEnvironment['FILE_PATH']}/second.properties</value>
            <value>file:#{systemEnvironment['FILE_PATH']}/third.properties</value>
        </list>
    </property>
</bean>

之后,您应该有一个名为“ FILE_PATH”的环境变量。确保在创建该环境变量后重新启动终端/ IDE。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.