comment lire la variable d'environnement système dans l'application Spring

116

Comment lire la variable d'environnement système dans le contexte de l'application?

Je veux quelque chose comme:

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

ou

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

en fonction de l'environnement.

Puis-je avoir quelque chose comme ça dans mon contexte d'application?

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

où la valeur réelle est définie en fonction de la VARIABLE D'ENVIRONNEMENT DU SYSTÈME

J'utilise Spring 3.0

I have
la source

Réponses:

106

Vous êtes proche: o) Spring 3.0 ajoute Spring Expression Language . Vous pouvez utiliser

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

Combiné avec java ... -Denv=QAdevrait résoudre votre problème.

Notez également un commentaire de @yiling:

Afin d'accéder à la variable d'environnement système, c'est-à-dire aux variables de niveau OS comme l'a commenté amoe, nous pouvons simplement utiliser "systemEnvironment" au lieu de "systemProperties" dans ce EL. Comme #{systemEnvironment['ENV_VARIABLE_NAME']}

amra
la source
qu'est-ce que java ... -Denv = QA signifie?
fresh_dev
2
Vous définissez une valeur de propriété système Java. Vous pouvez lire cette valeur dans le code commeassert System.getProperty("env") == "QA";
amra
Je pense que cette réponse est incorrecte, cela ne permet pas de lire les variables d'environnement du système (c'est-à-dire les variables au niveau du système d'exploitation définies avec export, etc.), cela permet uniquement de lire les propriétés du système Java.
amoe
2
-Dprop = ... définit une propriété java en ligne de commande. Vous pouvez lire cette propriété via System.getProperty("prop"). Si vous souhaitez lire une propriété du système d'exploitation, utilisez System.getenv("os-env-variable"). Voir javadoc: docs.oracle.com/javase/6/docs/api/java/lang/System.html
amra
22
Afin d'accéder à la variable d'environnement système, c'est-à-dire aux variables de niveau OS comme l'a commenté amoe, nous pouvons simplement utiliser "systemEnvironment" au lieu de "systemProperties" dans ce EL. Comme #{systemEnvironment['ENV_VARIABLE_NAME']}.
Yiling
51

De nos jours, vous pouvez mettre

@Autowired
private Environment environment;

dans votre @Component, @Beanetc., puis accéder aux propriétés par la Environmentclasse:

environment.getProperty("myProp");

Pour une seule propriété dans un@Bean

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

Une autre façon sont les @ConfigurationPropertiesharicots pratiques :

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

Remarque: n'oubliez pas de redémarrer eclipse après avoir défini une nouvelle variable d'environnement

Dariusz
la source
1
Les variables d'environnement sont-elles également accessibles via l' Environmentinterface?
Nikhil Sahu
@NikhilSahu Oui, ils le sont. Vous y accédez avec la même clé que vous le feriez lors d'une requête, java.lang.Systempar exemple pour obtenir le type de système d'exploitation que vous feriez en env.getProperty("os.name")supposant qu'il envs'agit de votre instance org.springframework.core.env.Environment.
Ninetou
1
@Autowired private Environment environment;ne fonctionne pas pour mon Componentenvironnement est toujours nul
a_horse_with_no_name
26

Oui, vous pouvez le faire <property name="defaultLocale" value="#{ systemProperties['user.region']}"/>par exemple.

La variable systemProperties est prédéfinie, voir 6.4.1 Configuration basée sur XML .

Istao
la source
8

Dans votre définition de bean, assurez-vous d'inclure "searchSystemEnvironment" et de le définir sur "true". Et si vous l'utilisez pour créer un chemin vers un fichier, spécifiez-le sous forme de fichier: /// url.

Par exemple, si vous avez un fichier de configuration situé dans

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

puis définissez une variable d'environnement comme ceci:

MY_ENV_VAR_PATH=/testapp/config

et votre application peut charger le fichier en utilisant une définition de bean comme celle-ci:

par exemple

<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
la source
8

En utilisant Spring EL, vous pouvez écrire un exemple comme suit

<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
la source
5

Pour mon cas d'utilisation, je devais accéder uniquement aux propriétés du système, mais fournir des valeurs par défaut au cas où elles ne seraient pas définies.

Voici comment vous procédez:

<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
la source
4

Déclarez l'espace réservé de propriété comme suit

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

Ensuite, disons que vous voulez lire System.property("java.io.tmpdir")pour votre bean Tomcat ou n'importe quel bean, puis ajoutez ce qui suit dans votre fichier de propriétés:

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

Voici comment vous procédez:

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

Mais rappelez-vous que le printemps est chargé en premier, puis il chargera ce bean MethodInvokingFactoryBean. Donc, si vous essayez d'utiliser ceci pour votre scénario de test, assurez-vous d'utiliser depend-on. Par exemple dans ce cas

Si vous l'utilisez pour votre classe principale, mieux vaut définir cette propriété en utilisant votre pom.xml comme

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

Vous pouvez mentionner vos attributs de variable dans un fichier de propriétés et définir des fichiers de propriétés spécifiques à l'environnement comme local.properties, production.propertied, etc.

Maintenant en fonction de l'environnement, l'un de ces fichiers de propriétés peut être lu dans l'un des écouteurs appelés au démarrage, comme le ServletContextListener.

Le fichier de propriétés contiendra les valeurs spécifiques à l'environnement pour différentes clés.

Exemple de "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

Exemple de "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

Pour utiliser ce fichier de propriétés, vous pouvez utiliser REsource comme mentionné ci-dessous

        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 peut être défini comme la variable d'environnement avec des valeurs appropriées pour l'environnement local et de production.

Avec ces modifications, appplicationContext.xml aura les modifications suivantes

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

J'espère que cela t'aides .

Sunil
la source
1

Merci à @Yiling. C'était un indice.

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

Après cela, vous devriez avoir une variable d'environnement nommée 'FILE_PATH'. Assurez-vous de redémarrer votre terminal / IDE après avoir créé cette variable d'environnement.

Jaikrat
la source