как читать системную переменную среды в 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

джай
источник

Ответы:

51

Проверьте эту статью . Это дает вам несколько способов сделать это, используя, PropertyPlaceholderConfigurerкоторый поддерживает внешние свойства (через systemPropertiesModeсвойство).

Bozho
источник
106

Вы близки: o) Spring 3.0 добавляет Spring Expression Language . Ты можешь использовать

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

В сочетании с java ... -Denv=QAдолжно решить вашу проблему.

Обратите внимание на комментарий @yiling:

Чтобы получить доступ к системной переменной среды, то есть к переменным уровня ОС, как прокомментировал я, мы можем просто использовать "systemEnvironment" вместо "systemProperties" в этом EL. подобно #{systemEnvironment['ENV_VARIABLE_NAME']}

Амра
источник
что означает java ... -Denv = QA?
fresh_dev
2
Вы устанавливаете значение свойства системы Java. Вы можете прочитать это значение в коде вродеassert System.getProperty("env") == "QA";
amra
Я думаю, что этот ответ неверен, он не позволяет читать системные переменные среды (т.е. переменные уровня ОС, установленные с помощью exportи т.д.), он позволяет только читать системные свойства Java.
Amoe
2
-Dprop = ... устанавливает свойство java в командной строке. Вы можете прочитать это свойство через System.getProperty("prop"). Если вы хотите прочитать свойство ОС, используйте System.getenv("os-env-variable"). См. Javadoc
amra
22
Чтобы получить доступ к системной переменной среды, то есть к переменным уровня ОС, как прокомментировал я, мы можем просто использовать "systemEnvironment" вместо "systemProperties" в этом EL. Нравится #{systemEnvironment['ENV_VARIABLE_NAME']}.
Yiling
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
Доступны ли переменные env через Environmentинтерфейс?
Nikhil Sahu
@NikhilSahu Да, это так. Вы java.lang.Systemполучаете к ним доступ с тем же ключом, что и при запросе, например, чтобы получить тип ОС, который, как вы env.getProperty("os.name")предполагаете, envявляется вашим экземпляром org.springframework.core.env.Environment.
Ninetou
1
@Autowired private Environment environment;не работает для моего Componentокружения всегда null
a_horse_with_no_name 05
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>
Mikus
источник
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")свой bean-компонент Tomcat или любой компонент, а затем добавьте следующее в свой файл свойств:

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, а затем загружается этот компонент MethodInvokingFactoryBean. Так что, если вы пытаетесь использовать это в своем тестовом примере, убедитесь, что вы используете файл depends-on. Например, в этом случае

Если вы используете его для своего основного класса, лучше установить это свойство, используя свой pom.xml как

<systemProperty>
    <name>deployment.env</name>
    <value>dev</value>
</systemProperty>
Атит Шах
источник
1

Вы можете указать свои атрибуты переменных в файле свойств и определить файлы свойств для конкретной среды, такие как local.properties, production.propertied и т. Д.

Теперь, в зависимости от среды, один из этих файлов свойств может быть прочитан в одном из прослушивателей, вызываемых при запуске, например ServletContextListener.

Файл свойств будет содержать специфические для среды значения для различных ключей.

Пример "local.propeties"

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 после создания этой переменной среды.

Jaikrat
источник