cara membaca variabel lingkungan Sistem di Spring applicationContext

116

Bagaimana membaca variabel lingkungan sistem dalam konteks aplikasi?

Saya ingin sesuatu seperti:

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

atau

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

tergantung pada lingkungan.

Dapatkah saya memiliki sesuatu seperti ini dalam Konteks aplikasi saya?

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

di mana nilai sebenarnya ditetapkan berdasarkan VARIABEL LINGKUNGAN SISTEM

Saya menggunakan Spring 3.0

jai
sumber

Jawaban:

106

Anda sudah dekat: o) Spring 3.0 menambahkan Spring Expression Language . Kamu bisa memakai

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

Dikombinasikan dengan java ... -Denv=QAharus menyelesaikan masalah Anda.

Perhatikan juga komentar oleh @yiling:

Untuk mengakses variabel lingkungan sistem, yaitu variabel tingkat OS seperti yang dikomentari, kita cukup menggunakan "systemEnvironment" daripada "systemProperties" di EL itu. Suka #{systemEnvironment['ENV_VARIABLE_NAME']}

amra
sumber
apa itu java ... -Denv = QA?
fresh_dev
2
Anda menyetel nilai properti sistem java. Anda dapat membaca nilai ini dalam kode sepertiassert System.getProperty("env") == "QA";
amra
Saya pikir jawaban ini salah, ini tidak memungkinkan membaca variabel lingkungan sistem (yaitu variabel tingkat OS yang diatur dengan export, dll), ini hanya memungkinkan membaca properti sistem Java.
amoe
2
-Dprop = ... menyetel properti java di baris perintah. Anda dapat membaca properti ini melalui System.getProperty("prop"). Jika Anda ingin membaca properti OS, gunakan System.getenv("os-env-variable"). Lihat javadoc: docs.oracle.com/javase/6/docs/api/java/lang/System.html
amra
22
Untuk mengakses variabel lingkungan sistem, yaitu variabel tingkat OS seperti yang dikomentari, kita cukup menggunakan "systemEnvironment" daripada "systemProperties" di EL itu. Suka #{systemEnvironment['ENV_VARIABLE_NAME']}.
Yiling
51

Saat ini Anda bisa menempatkan

@Autowired
private Environment environment;

di Anda @Component,, @Beandll., lalu akses properti melalui Environmentkelas:

environment.getProperty("myProp");

Untuk satu properti di a@Bean

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

Cara lain adalah @ConfigurationPropertieskacang praktis :

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

Catatan: Ingatlah untuk memulai ulang eclipse setelah menyetel variabel lingkungan baru

Dariusz
sumber
1
Apakah variabel env juga dapat diakses melalui Environmentantarmuka?
Nikhil Sahu
@NikhilSahu Ya, mereka. Anda mengaksesnya dengan kunci yang sama seperti yang Anda lakukan saat melakukan kueri, java.lang.Systemmisalnya untuk mendapatkan jenis OS yang Anda env.getProperty("os.name")anggap sebagai envinstance Anda org.springframework.core.env.Environment.
Sembilan puluh
1
@Autowired private Environment environment;tidak bekerja untuk Componentlingkungan saya selalu null
a_horse_with_no_name
26

Ya, Anda bisa melakukannya <property name="defaultLocale" value="#{ systemProperties['user.region']}"/>misalnya.

Variabel systemProperties sudah ditentukan sebelumnya, lihat 6.4.1 konfigurasi berbasis XML .

Istao
sumber
8

Dalam definisi kacang Anda, pastikan untuk menyertakan "searchSystemEnvironment" dan setel ke "true". Dan jika Anda menggunakannya untuk membuat jalur ke file, tentukan sebagai file: /// url.

Jadi misalnya, jika Anda memiliki file konfigurasi yang terletak di

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

kemudian atur variabel lingkungan seperti ini:

MY_ENV_VAR_PATH=/testapp/config

dan aplikasi Anda dapat memuat file menggunakan definisi kacang seperti ini:

misalnya

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

Menggunakan Spring EL Anda dapat melihat contoh tulis sebagai berikut

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

Untuk kasus penggunaan saya, saya hanya perlu mengakses properti sistem, tetapi memberikan nilai default jika tidak ditentukan.

Beginilah cara Anda melakukannya:

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

Nyatakan pemilik tempat properti sebagai berikut

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

Kemudian katakanlah Anda ingin membaca System.property("java.io.tmpdir")untuk kacang Tomcat atau kacang apa pun lalu tambahkan berikut ini di file properti Anda:

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

Beginilah cara Anda melakukannya:

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

Tapi ingat musim semi dimuat terlebih dahulu dan kemudian itu akan memuat kacang ini MethodInvokingFactoryBean. Jadi jika Anda mencoba menggunakan ini untuk kasus pengujian Anda, maka pastikan bahwa Anda menggunakan tergantung. Misalnya dalam kasus ini

Jika Anda menggunakannya untuk kelas utama Anda, sebaiknya setel properti ini menggunakan pom.xml Anda sebagai

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

Anda dapat menyebutkan atribut variabel Anda dalam file properti dan menentukan file properti khusus lingkungan seperti local.properties, production.propertied, dll.

Sekarang berdasarkan lingkungan, salah satu file properti ini dapat dibaca di salah satu pemroses yang dipanggil saat startup, seperti ServletContextListener.

File properti akan berisi nilai spesifik lingkungan untuk berbagai kunci.

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

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

Untuk menggunakan file properti ini, Anda dapat menggunakan REsource seperti yang disebutkan di bawah ini

        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 dapat didefinisikan sebagai variabel lingkungan dengan nilai yang sesuai untuk lingkungan lokal dan produksi.

Dengan perubahan ini, appplicationContext.xml akan memiliki perubahan berikut

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

Semoga ini membantu .

Sunil
sumber
1

Terima kasih kepada @Yiling. Itu adalah petunjuk.

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

Setelah ini, Anda harus memiliki satu variabel lingkungan bernama 'FILE_PATH'. Pastikan Anda memulai ulang terminal / IDE Anda setelah membuat variabel lingkungan itu.

Jaikrat
sumber