Lesen der Systemumgebungsvariablen in Spring applicationContext

116

Wie lese ich die Systemumgebungsvariable im Anwendungskontext?

Ich möchte so etwas wie:

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

oder

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

abhängig von der Umgebung.

Kann ich so etwas in meinem Anwendungskontext haben?

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

Dabei wird der tatsächliche Wert basierend auf der VARIABLEN SYSTEMUMGEBUNG festgelegt

Ich benutze Spring 3.0

jai
quelle

Antworten:

106

Sie sind nah dran: o) Spring 3.0 fügt Spring Expression Language hinzu . Sie können verwenden

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

Kombiniert mit java ... -Denv=QAsollte Ihr Problem lösen.

Beachten Sie auch einen Kommentar von @yiling:

Um auf Systemumgebungsvariablen zuzugreifen, dh auf Variablen auf Betriebssystemebene, wie amoe kommentiert hat, können wir in dieser EL einfach "systemEnvironment" anstelle von "systemProperties" verwenden. Mögen #{systemEnvironment['ENV_VARIABLE_NAME']}

amra
quelle
Was ist Java ... -Denv = QA bedeutet?
fresh_dev
2
Sie legen einen Java-Systemeigenschaftswert fest. Sie können diesen Wert in Code wieassert System.getProperty("env") == "QA";
amra
Ich denke, diese Antwort ist falsch. Dies erlaubt nicht das Lesen von Systemumgebungsvariablen (dh Variablen auf Betriebssystemebene, die mit festgelegt exportsind usw.), sondern nur das Lesen von Java-Systemeigenschaften.
Amoe
2
-Dprop = ... legt eine Java-Eigenschaft in der Befehlszeile fest. Sie können diese Eigenschaft über lesen System.getProperty("prop"). Wenn Sie eine Betriebssystemeigenschaft lesen möchten, verwenden Sie System.getenv("os-env-variable"). Siehe javadoc: docs.oracle.com/javase/6/docs/api/java/lang/System.html
amra
22
Um auf Systemumgebungsvariablen zuzugreifen, dh auf Variablen auf Betriebssystemebene, wie amoe kommentiert hat, können wir in dieser EL einfach "systemEnvironment" anstelle von "systemProperties" verwenden. Wie #{systemEnvironment['ENV_VARIABLE_NAME']}.
Yiling
51

Heutzutage kann man setzen

@Autowired
private Environment environment;

in Ihrem @Component, @Beanusw. und dann Zugriff auf die Eigenschaften durch die EnvironmentKlasse:

environment.getProperty("myProp");

Für eine einzelne Immobilie in a@Bean

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

Ein anderer Weg sind die handlichen @ConfigurationPropertiesBohnen:

@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;
}

Hinweis: Denken Sie daran, Eclipse nach dem Festlegen einer neuen Umgebungsvariablen neu zu starten

Dariusz
quelle
1
Sind env-Variablen auch über die EnvironmentSchnittstelle zugänglich ?
Nikhil Sahu
@NikhilSahu Ja, das sind sie. Sie greifen mit demselben Schlüssel auf sie zu, wie Sie es bei der Abfrage java.lang.Systemtun würden, z. B. um den Betriebssystemtyp zu erhalten, von dem Sie env.getProperty("os.name")annehmen würden, dass er envIhre Instanz von ist org.springframework.core.env.Environment.
Ninetou
1
@Autowired private Environment environment;funktioniert nicht für mich Componentdie Umgebung ist immer null
a_horse_with_no_name
26

Ja, das können Sie <property name="defaultLocale" value="#{ systemProperties['user.region']}"/>zum Beispiel tun .

Die Variable systemProperties ist vordefiniert, siehe 6.4.1 XML-basierte Konfiguration .

Istao
quelle
8

Stellen Sie in Ihrer Bean-Definition sicher, dass "searchSystemEnvironment" enthalten ist, und setzen Sie es auf "true". Wenn Sie damit einen Pfad zu einer Datei erstellen, geben Sie ihn als Datei an: /// url.

Zum Beispiel, wenn Sie eine Konfigurationsdatei in haben

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

Stellen Sie dann eine Umgebungsvariable wie folgt ein:

MY_ENV_VAR_PATH=/testapp/config

und Ihre App kann die Datei mit einer Bean-Definition wie folgt laden:

z.B

<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>
Brad Parks
quelle
8

Mit Spring EL können Sie beispielsweise wie folgt schreiben

<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
quelle
5

Für meinen Anwendungsfall musste ich nur auf die Systemeigenschaften zugreifen, aber Standardwerte angeben, falls diese nicht definiert sind.

Das ist wie man es macht:

<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>
eis
quelle
4

Erklären Sie den Platzhalter wie folgt

<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>

Nehmen wir dann an, Sie möchten System.property("java.io.tmpdir")für Ihre Tomcat-Bean oder eine beliebige Bean lesen und fügen in Ihrer Eigenschaftendatei Folgendes hinzu:

tomcat.tmp.dir=${java.io.tmpdir}
Justin Patel
quelle
1

Das ist wie man es macht:

<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>

Denken Sie jedoch daran, dass die Feder zuerst geladen wird und dann diese Bean MethodInvokingFactoryBean lädt. Wenn Sie also versuchen, dies für Ihren Testfall zu verwenden, stellen Sie sicher, dass Sie abhängig davon verwenden. Zum Beispiel in diesem Fall

Wenn Sie es für Ihre Hauptklasse verwenden, legen Sie diese Eigenschaft besser mit Ihrer pom.xml als fest

<systemProperty>
    <name>deployment.env</name>
    <value>dev</value>
</systemProperty>
Atit Shah
quelle
1

Sie können Ihre Variablenattribute in einer Eigenschaftendatei erwähnen und umgebungsspezifische Eigenschaftendateien wie local.properties, Production.propertied usw. definieren.

Basierend auf der Umgebung kann nun eine dieser Eigenschaftendateien in einer der beim Start aufgerufenen Listener gelesen werden, z. B. im ServletContextListener.

Die Eigenschaftendatei enthält die umgebungsspezifischen Werte für verschiedene Schlüssel.

Beispiel "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

Beispiel "Produktion.Eigenschaften"

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

Für die Verwendung dieser Eigenschaftendatei können Sie REsource wie unten beschrieben verwenden

        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 kann als Umgebungsvariable mit geeigneten Werten für die lokale Umgebung und die Produktionsumgebung definiert werden.

Mit diesen Änderungen hat die appplicationContext.xml die folgenden Änderungen

<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}" />

Hoffe das hilft .

Sunil
quelle
1

Danke an @Yiling. Das war ein Hinweis.

<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>

Danach sollten Sie eine Umgebungsvariable mit dem Namen 'FILE_PATH' haben. Stellen Sie sicher, dass Sie Ihr Terminal / Ihre IDE neu starten, nachdem Sie diese Umgebungsvariable erstellt haben.

Jaikrat
quelle