cómo leer la variable de entorno del sistema en Spring applicationContext

116

¿Cómo leer la variable de entorno del sistema en el contexto de la aplicación?

Quiero algo como:

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

o

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

dependiendo del entorno.

¿Puedo tener algo como esto en el contexto de mi aplicación?

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

donde el valor real se establece según la VARIABLE DEL ENTORNO DEL SISTEMA

Estoy usando Spring 3.0

jai
fuente

Respuestas:

106

Estás cerca: o) Spring 3.0 agrega Spring Expression Language . Puedes usar

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

Combinado con java ... -Denv=QA debería resolver su problema.

Tenga en cuenta también un comentario de @yiling:

Para acceder a la variable de entorno del sistema, es decir, las variables de nivel de sistema operativo como comentó amoe, podemos simplemente usar "systemEnvironment" en lugar de "systemProperties" en ese EL. Me gusta #{systemEnvironment['ENV_VARIABLE_NAME']}

amra
fuente
¿Qué significa java ... -Denv = QA?
fresh_dev
2
Establece un valor de propiedad del sistema java. Puede leer este valor en código comoassert System.getProperty("env") == "QA";
amra
Creo que esta respuesta es incorrecta, esto no permite leer las variables de entorno del sistema (es decir, las variables de nivel de sistema operativo configuradas con export, etc.), solo permite leer las propiedades del sistema Java.
ame
2
-Dprop = ... establece una propiedad java en la línea de comandos. Puede leer esta propiedad a través de System.getProperty("prop"). Si desea leer una propiedad del sistema operativo, utilice System.getenv("os-env-variable"). Ver javadoc: docs.oracle.com/javase/6/docs/api/java/lang/System.html
amra
22
Para acceder a la variable de entorno del sistema, es decir, las variables de nivel de sistema operativo como comentó amoe, podemos simplemente usar "systemEnvironment" en lugar de "systemProperties" en ese EL. Al igual #{systemEnvironment['ENV_VARIABLE_NAME']}.
Yiling
51

Hoy en día puedes poner

@Autowired
private Environment environment;

en su @Component, @Bean, etc, y luego acceder a las propiedades a través de la Environmentclase:

environment.getProperty("myProp");

Para una sola propiedad en un@Bean

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

Otra forma son los prácticos @ConfigurationPropertiesfrijoles:

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

Nota: solo recuerde reiniciar eclipse después de configurar una nueva variable de entorno

Dariusz
fuente
1
¿Las variables env también son accesibles a través de la Environmentinterfaz?
Nikhil Sahu
@NikhilSahu Sí, lo son. Puede acceder a ellos con la misma clave que lo haría al consultar, java.lang.Systempor ejemplo, para obtener el tipo de sistema operativo que haría env.getProperty("os.name")asumiendo que enves su instancia de org.springframework.core.env.Environment.
Ninetou
1
@Autowired private Environment environment;no funciona para mi Componentel entorno siempre es nulo
a_horse_with_no_name
26

Sí, puede hacerlo, <property name="defaultLocale" value="#{ systemProperties['user.region']}"/>por ejemplo.

La variable systemProperties está predefinida, consulte 6.4.1 Configuración basada en XML .

Istao
fuente
8

En su definición de bean, asegúrese de incluir "searchSystemEnvironment" y establézcalo en "true". Y si lo está utilizando para crear una ruta a un archivo, especifíquelo como file: /// url.

Entonces, por ejemplo, si tiene un archivo de configuración ubicado en

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

luego establezca una variable de entorno así:

MY_ENV_VAR_PATH=/testapp/config

y su aplicación puede cargar el archivo usando una definición de frijol como esta:

p.ej

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

Utilizando Spring EL puede EIS ejemplo de escritura de la siguiente

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

Para mi caso de uso, necesitaba acceder solo a las propiedades del sistema, pero proporcionar valores predeterminados en caso de que no estén definidos.

Así es como lo haces:

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

Declare el marcador de posición de propiedad de la siguiente manera

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

Luego, digamos que desea leer System.property("java.io.tmpdir")su bean Tomcat o cualquier bean y luego agregue lo siguiente en su archivo de propiedades:

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

Así es como lo haces:

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

Pero recuerde que el resorte se carga primero y luego cargará este bean MethodInvokingFactoryBean. Entonces, si está tratando de usar esto para su caso de prueba, asegúrese de usar depende de. Por ejemplo, en este caso

En caso de que lo esté usando para su clase principal, es mejor establecer esta propiedad usando su pom.xml como

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

Puede mencionar los atributos de sus variables en un archivo de propiedades y definir archivos de propiedades específicos del entorno como local.properties, production.propertied, etc.

Ahora, según el entorno, uno de estos archivos de propiedades se puede leer en uno de los oyentes invocados al inicio, como ServletContextListener.

El archivo de propiedades contendrá los valores específicos del entorno para varias claves.

Muestra "locales.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

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

Para usar este archivo de propiedades, puede hacer uso de REsource como se menciona a continuación

        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 se puede definir como la variable de entorno con los valores adecuados para el entorno local y de producción.

Con estos cambios, appplicationContext.xml tendrá los siguientes cambios

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

Espero que esto ayude .

Sunil
fuente
1

Gracias a @Yiling. Eso fue una pista.

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

Después de esto, debería tener una variable de entorno llamada 'FILE_PATH'. Asegúrese de reiniciar su terminal / IDE después de crear esa variable de entorno.

Jaikrat
fuente