Làm thế nào để đọc biến môi trường hệ thống trong ứng dụng SpringContext


116

Làm thế nào để đọc biến môi trường hệ thống trong ngữ cảnh ứng dụng?

Tôi muốn một cái gì đó như:

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

hoặc là

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

tùy thuộc vào môi trường.

Tôi có thể có một cái gì đó như thế này trong bối cảnh ứng dụng của tôi?

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

trong đó val thực tế được đặt dựa trên BIẾN MÔI TRƯỜNG HỆ THỐNG

Tôi đang sử dụng Spring 3.0

Câu trả lời:



106

Bạn đang ở gần: o) Spring 3.0 thêm Ngôn ngữ biểu thức mùa xuân . Bạn có thể dùng

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

Kết hợp với java ... -Denv=QAnên giải quyết vấn đề của bạn.

Cũng lưu ý một nhận xét của @yiling:

Để truy cập biến môi trường hệ thống, đó là biến cấp độ hệ điều hành như amoe đã nhận xét, chúng ta chỉ cần sử dụng "systemEn Môi trường" thay vì "systemProperies" trong EL đó. Giống #{systemEnvironment['ENV_VARIABLE_NAME']}


java ... -Denv = QA nghĩa là gì?
Fresh_dev

2
Bạn đặt một giá trị thuộc tính hệ thống java. Bạn có thể đọc giá trị này trong mã nhưassert System.getProperty("env") == "QA";
amra

Tôi nghĩ rằng câu trả lời này không chính xác, điều này không cho phép đọc các biến môi trường hệ thống (ví dụ: các biến cấp độ hệ điều hành được đặt với export, v.v.), nó chỉ cho phép đọc các thuộc tính hệ thống Java.
amoe

2
-Dprop = ... đặt thuộc tính java trong dòng lệnh. Bạn có thể đọc tài sản này thông qua System.getProperty("prop"). Nếu bạn muốn đọc một thuộc tính hệ điều hành thì hãy sử dụng System.getenv("os-env-variable"). Xem javadoc: docs.oracle.com/javase/6/docs/api/java/lang/System.html
amra

22
Để truy cập biến môi trường hệ thống, đó là biến cấp độ hệ điều hành như amoe đã nhận xét, chúng ta chỉ cần sử dụng "systemEn Môi trường" thay vì "systemProperies" trong EL đó. Thích #{systemEnvironment['ENV_VARIABLE_NAME']}.
Yiling

51

Ngày nay bạn có thể đặt

@Autowired
private Environment environment;

trong của bạn @Component, @Beanvv, và sau đó truy cập vào các thuộc tính thông qua các Environmentlớp:

environment.getProperty("myProp");

Đối với một tài sản duy nhất trong một@Bean

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

Một cách khác@ConfigurationPropertiesđậu tiện dụng :

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

Lưu ý: Chỉ cần nhớ khởi động lại nhật thực sau khi đặt biến môi trường mới


1
Các biến env cũng có thể truy cập thông qua Environmentgiao diện?
Nikhil Sahu

@NikhilSahu Vâng, đúng vậy. Bạn truy cập chúng với phím giống như bạn khi truy vấn java.lang.Systemví dụ để có được loại hệ điều hành bạn muốn làm env.getProperty("os.name")giả envlà bạn thể hiện của org.springframework.core.env.Environment.
Ninetou

1
@Autowired private Environment environment;không hoạt động đối Componentvới môi trường của tôi luôn là null
a_horse_with_no_name

26

Vâng, bạn có thể làm <property name="defaultLocale" value="#{ systemProperties['user.region']}"/>ví dụ.

Các hệ thống biến đổi được xác định trước, xem cấu hình dựa trên XML 6.4.1 .


8

Trong định nghĩa bean của bạn, đảm bảo bao gồm "searchSystemEn Môi trường" và đặt nó thành "true". Và nếu bạn đang sử dụng nó để xây dựng đường dẫn đến một tệp, hãy chỉ định nó dưới dạng tệp: /// url.

Vì vậy, ví dụ, nếu bạn có một tệp cấu hình nằm trong

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

sau đó đặt biến môi trường như vậy:

MY_ENV_VAR_PATH=/testapp/config

và ứng dụng của bạn có thể tải tệp bằng định nghĩa bean như thế này:

ví dụ

<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

Sử dụng Spring EL, bạn có thể viết ví dụ như sau

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

5

Đối với trường hợp sử dụng của tôi, tôi chỉ cần truy cập các thuộc tính hệ thống, nhưng cung cấp các giá trị mặc định trong trường hợp chúng không được xác định.

Đây là cách bạn làm điều đó:

<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

Khai báo chủ sở hữu tài sản như sau

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

Sau đó, giả sử bạn muốn đọc System.property("java.io.tmpdir")cho Tomcat bean hoặc bất kỳ bean nào sau đó thêm vào sau trong tệp thuộc tính của bạn:

tomcat.tmp.dir=${java.io.tmpdir}

1

Đây là cách bạn làm điều đó:

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

Nhưng hãy nhớ rằng mùa xuân được tải trước và sau đó nó sẽ tải phương thức bean nàyInvokingFactoryBean. Vì vậy, nếu bạn đang cố gắng sử dụng điều này cho trường hợp thử nghiệm của mình thì hãy chắc chắn rằng bạn sử dụng tùy thuộc. Ví dụ trong trường hợp này

Trong trường hợp bạn đang sử dụng nó cho lớp chính của mình thì tốt hơn để đặt thuộc tính này bằng pom.xml của bạn như

<systemProperty>
    <name>deployment.env</name>
    <value>dev</value>
</systemProperty>

1

Bạn có thể đề cập đến các thuộc tính biến của mình trong tệp thuộc tính và xác định các tệp thuộc tính cụ thể của môi trường như local.properies, Production.propertied, v.v.

Bây giờ dựa trên môi trường, một trong những tệp thuộc tính này có thể được đọc trong một trình nghe được gọi khi khởi động, như ServletContextListener.

Tệp thuộc tính sẽ chứa các giá trị cụ thể của môi trường cho các khóa khác nhau.

Mẫu "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

Mẫu "sản xuất. Sản phẩm"

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

Để sử dụng tệp thuộc tính này, bạn có thể sử dụng REsource như được đề cập dưới đây

        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 có thể được định nghĩa là biến môi trường với các giá trị phù hợp cho môi trường sản xuất và cục bộ.

Với những thay đổi này, appplicationContext.xml sẽ có các thay đổi sau

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

Hi vọng điêu nay co ich .


1

Cảm ơn @Yiling. Đó là một gợi ý.

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

Sau này, bạn sẽ có một biến môi trường có tên 'FILE_PATH'. Hãy chắc chắn rằng bạn khởi động lại terminal / IDE sau khi tạo biến môi trường đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.