วิธีอ่านตัวแปรสภาพแวดล้อมระบบใน Spring applicationContext


116

จะอ่านตัวแปรสภาพแวดล้อมของระบบในบริบทแอปพลิเคชันได้อย่างไร?

ฉันต้องการสิ่งที่ชอบ:

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

หรือ

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

ขึ้นอยู่กับสภาพแวดล้อม

ฉันขอแบบนี้ในบริบทแอปพลิเคชันได้ไหม

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

โดยที่ค่าจริงถูกตั้งค่าตามตัวแปรสภาพแวดล้อมของระบบ

ฉันใช้ Spring 3.0

คำตอบ:


51

ตรวจสอบบทความนี้ มันช่วยให้คุณทำสิ่งนี้ได้หลายวิธีPropertyPlaceholderConfigurerซึ่งรองรับคุณสมบัติภายนอก (ผ่านsystemPropertiesModeคุณสมบัติ)


106

คุณอยู่ใกล้: o) ฤดูใบไม้ผลิ 3.0 เพิ่มฤดูใบไม้ผลิการแสดงออกภาษา คุณสามารถใช้ได้

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

รวมกับjava ... -Denv=QAควรแก้ปัญหาของคุณ

หมายเหตุยังแสดงความคิดเห็นโดย @yiling:

ในการเข้าถึงตัวแปรสภาพแวดล้อมระบบนั่นคือตัวแปรระดับ OS ตามที่ Amoe แสดงความคิดเห็นเราสามารถใช้ "systemEnvironment" แทน "systemProperties" ใน EL นั้นได้ ชอบ #{systemEnvironment['ENV_VARIABLE_NAME']}


java ... -Denv = QA หมายถึงอะไร
fresh_dev

2
คุณตั้งค่าคุณสมบัติระบบ java คุณสามารถอ่านค่านี้ในรหัสเช่นassert System.getProperty("env") == "QA";
amra

ฉันคิดว่าคำตอบนี้ไม่ถูกต้องไม่อนุญาตให้อ่านตัวแปรสภาพแวดล้อมของระบบ (เช่นตัวแปรระดับ OS ที่ตั้งค่าด้วยexportฯลฯ ) อนุญาตให้อ่านคุณสมบัติของระบบ Java เท่านั้น
amoe

2
-Dprop = ... ตั้งค่าคุณสมบัติ java ในบรรทัดคำสั่ง System.getProperty("prop")คุณสามารถอ่านคุณสมบัตินี้ผ่านทาง หากคุณต้องการที่จะอ่านคุณสมบัติ OS System.getenv("os-env-variable")แล้วใช้ ดู javadoc: docs.oracle.com/javase/6/docs/api/java/lang/System.html
amra

22
ในการเข้าถึงตัวแปรสภาพแวดล้อมระบบนั่นคือตัวแปรระดับ OS ตามที่ Amoe แสดงความคิดเห็นเราสามารถใช้ "systemEnvironment" แทน "systemProperties" ใน EL นั้นได้ ชอบ#{systemEnvironment['ENV_VARIABLE_NAME']}.
Yiling

51

ปัจจุบันคุณสามารถใส่

@Autowired
private Environment environment;

ในของคุณ@Component, @Beanฯลฯ และจากนั้นเข้าถึงคุณสมบัติผ่านEnvironmentชั้น:

environment.getProperty("myProp");

สำหรับคุณสมบัติเดียวใน@Bean

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

อีกวิธีหนึ่งคือ@ConfigurationPropertiesถั่วที่มีประโยชน์:

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

หมายเหตุ: อย่าลืมรีสตาร์ท eclipse หลังจากตั้งค่าตัวแปรสภาพแวดล้อมใหม่


1
สามารถเข้าถึงตัวแปร env ผ่านEnvironmentอินเทอร์เฟซได้หรือไม่
Nikhil Sahu

@NikhilSahu ใช่พวกเขา คุณเข้าถึงด้วยคีย์เดียวกับที่คุณต้องการเมื่อทำการค้นหาjava.lang.Systemเช่นเพื่อรับประเภท OS ที่คุณคิดenv.getProperty("os.name")ว่าenvเป็นอินสแตนซ์ของorg.springframework.core.env.Environmentคุณ
Ninetou

1
@Autowired private Environment environment;ใช้ไม่ได้Componentกับสภาพแวดล้อมของฉันเป็นโมฆะเสมอ
a_horse_with_no_name

26

ใช่คุณสามารถทำได้<property name="defaultLocale" value="#{ systemProperties['user.region']}"/>เช่น

ตัวแปรsystemPropertiesกำหนดไว้ล่วงหน้าให้ดูที่การกำหนดค่าตาม 6.4.1 XML


8

ในคำจำกัดความ bean ของคุณตรวจสอบให้แน่ใจว่าได้รวม "searchSystemEnvironment" และตั้งค่าเป็น "true" และหากคุณใช้เพื่อสร้างเส้นทางไปยังไฟล์ให้ระบุเป็นไฟล์: /// url

ตัวอย่างเช่นหากคุณมีไฟล์กำหนดค่าอยู่ใน

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

จากนั้นตั้งค่าตัวแปรสภาพแวดล้อมดังนี้:

MY_ENV_VAR_PATH=/testapp/config

และแอปของคุณสามารถโหลดไฟล์โดยใช้คำจำกัดความของ bean ดังนี้:

เช่น

<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

การใช้ Spring EL คุณสามารถเขียนตัวอย่างได้ดังนี้

<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

สำหรับกรณีการใช้งานของฉันฉันต้องการเข้าถึงเฉพาะคุณสมบัติของระบบ แต่ระบุค่าเริ่มต้นในกรณีที่ไม่ได้กำหนดไว้

นี่คือวิธีที่คุณทำ:

<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

ประกาศผู้ถือครองทรัพย์สินดังต่อไปนี้

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

จากนั้นสมมติว่าคุณต้องการอ่านSystem.property("java.io.tmpdir")Tomcat bean หรือ bean ใด ๆ จากนั้นเพิ่มสิ่งต่อไปนี้ในไฟล์คุณสมบัติของคุณ:

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

1

นี่คือวิธีที่คุณทำ:

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

แต่จำไว้ว่าสปริงโหลดก่อนจากนั้นมันจะโหลด MethodInvokingFactoryBean ถั่วนี้ ดังนั้นหากคุณกำลังพยายามใช้สิ่งนี้สำหรับกรณีทดสอบของคุณให้แน่ใจว่าคุณใช้ขึ้นอยู่กับ เช่นในกรณีนี้

ในกรณีที่คุณใช้สำหรับคลาสหลักของคุณควรตั้งค่าคุณสมบัตินี้โดยใช้ pom.xml ของคุณเป็น

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

1

คุณสามารถกล่าวถึงแอ็ตทริบิวต์ตัวแปรของคุณในไฟล์คุณสมบัติและกำหนดไฟล์คุณสมบัติเฉพาะสภาวะแวดล้อมเช่น local.properties, production.propertied เป็นต้น

ตอนนี้ขึ้นอยู่กับสภาพแวดล้อมหนึ่งในไฟล์คุณสมบัติเหล่านี้สามารถอ่านได้ในไฟล์ที่ฟังเรียกเมื่อเริ่มต้นเช่น ServletContextListener

ไฟล์คุณสมบัติจะมีค่าเฉพาะสภาวะแวดล้อมสำหรับคีย์ต่างๆ

ตัวอย่าง "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

ตัวอย่าง "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

สำหรับการใช้ไฟล์คุณสมบัติเหล่านี้คุณสามารถใช้ REsource ดังที่กล่าวไว้ด้านล่าง

        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 สามารถกำหนดเป็นตัวแปรสภาพแวดล้อมที่มีค่าที่เหมาะสมสำหรับสภาพแวดล้อมโลคัลและสภาพแวดล้อมการผลิต

ด้วยการเปลี่ยนแปลงเหล่านี้ appplicationContext.xml จะมีการเปลี่ยนแปลงดังต่อไปนี้

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

หวังว่านี่จะช่วยได้


1

ขอบคุณ @Yiling นั่นเป็นคำใบ้

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

หลังจากนี้คุณควรมีตัวแปรสภาพแวดล้อมชื่อ 'FILE_PATH' ตรวจสอบให้แน่ใจว่าคุณรีสตาร์ทเทอร์มินัล / IDE ของคุณหลังจากสร้างตัวแปรสภาพแวดล้อมนั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.