jak czytać zmienną środowiskową systemu w Spring applicationContext

116

Jak czytać zmienną środowiskową systemu w kontekście aplikacji?

Chcę coś takiego:

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

lub

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

w zależności od środowiska.

Czy mogę mieć coś takiego w kontekście mojej aplikacji?

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

gdzie rzeczywista wartość jest ustawiana na podstawie ZMIENNEJ ŚRODOWISKA SYSTEMOWEGO

Używam Spring 3.0

jai
źródło

Odpowiedzi:

106

Jesteś blisko: o) Wiosna 3.0 dodaje język Spring Expression . Możesz użyć

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

W połączeniu z java ... -Denv=QApowinien rozwiązać twój problem.

Zwróć też uwagę na komentarz @yiling:

Aby uzyskać dostęp do zmiennej środowiskowej systemu, czyli zmiennych poziomu systemu operacyjnego, jak skomentował amoe, możemy po prostu użyć „systemEnvironment” zamiast „systemProperties” w tym EL. Lubić #{systemEnvironment['ENV_VARIABLE_NAME']}

amra
źródło
co to jest java ... -Denv = QA oznacza?
fresh_dev
2
Ustawiasz wartość właściwości systemowej Java. Możesz odczytać tę wartość w kodzie, takim jakassert System.getProperty("env") == "QA";
amra
Myślę, że ta odpowiedź jest niepoprawna, nie pozwala to na odczytywanie zmiennych środowiskowych systemu (tj. Zmiennych na poziomie systemu operacyjnego ustawionych za pomocą exportitp.), Pozwala tylko na odczyt właściwości systemowych Java.
amoe
2
-Dprop = ... ustawia właściwość Java w wierszu poleceń. Możesz przeczytać tę właściwość za pośrednictwem System.getProperty("prop"). Jeśli chcesz przeczytać właściwość systemu operacyjnego, użyj System.getenv("os-env-variable"). Zobacz javadoc: docs.oracle.com/javase/6/docs/api/java/lang/System.html
amra,
22
Aby uzyskać dostęp do zmiennej środowiskowej systemu, czyli zmiennych poziomu systemu operacyjnego, jak skomentował amoe, możemy po prostu użyć „systemEnvironment” zamiast „systemProperties” w tym EL. Lubię #{systemEnvironment['ENV_VARIABLE_NAME']}.
Yiling
51

W dzisiejszych czasach możesz umieścić

@Autowired
private Environment environment;

w twoim @Component, @Beanitp., a następnie uzyskaj dostęp do właściwości za pośrednictwem Environmentklasy:

environment.getProperty("myProp");

W przypadku jednej nieruchomości w a@Bean

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

Innym sposobem są poręczne @ConfigurationPropertiesfasole:

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

Uwaga: pamiętaj tylko o ponownym uruchomieniu zaćmienia po ustawieniu nowej zmiennej środowiskowej

Dariusz
źródło
1
Czy zmienne env są również dostępne przez Environmentinterfejs?
Nikhil Sahu
@NikhilSahu Tak, są. Uzyskujesz do nich dostęp za pomocą tego samego klucza, co w przypadku zapytań, java.lang.Systemnp. W celu uzyskania typu systemu operacyjnego, env.getProperty("os.name")zakładając , że envjest to Twoja instancja org.springframework.core.env.Environment.
Ninetou
1
@Autowired private Environment environment;nie działa dla mojego Componentśrodowiska jest zawsze null
a_horse_with_no_name
26

Tak, możesz to zrobić <property name="defaultLocale" value="#{ systemProperties['user.region']}"/>na przykład.

Zmienna systemProperties jest wstępnie zdefiniowana, patrz 6.4.1 Konfiguracja oparta na języku XML .

Istao
źródło
8

W definicji komponentu bean pamiętaj, aby uwzględnić „searchSystemEnvironment” i ustawić je na „true”. A jeśli używasz go do budowania ścieżki do pliku, określ go jako plik: /// url.

Na przykład, jeśli masz plik konfiguracyjny znajdujący się w

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

następnie ustaw zmienną środowiskową w ten sposób:

MY_ENV_VAR_PATH=/testapp/config

a Twoja aplikacja może załadować plik przy użyciu takiej definicji komponentu bean:

na przykład

<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
źródło
8

Używając Spring EL, możesz na przykład napisać w następujący sposób

<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
źródło
5

W moim przypadku potrzebowałem uzyskać dostęp tylko do właściwości systemu, ale podać wartości domyślne na wypadek, gdyby były niezdefiniowane.

Tak to się robi:

<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
źródło
4

Zadeklaruj symbol zastępczy właściwości w następujący sposób

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

Następnie powiedzmy, że chcesz przeczytać informacje System.property("java.io.tmpdir")o ziarnie Tomcat lub innym ziarnie, a następnie dodaj następujące elementy w pliku właściwości:

tomcat.tmp.dir=${java.io.tmpdir}
Justin Patel
źródło
1

Tak to się robi:

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

Pamiętaj jednak, że najpierw ładuje się sprężynę, a następnie ładuje tę ziarno MethodInvokingFactoryBean. Więc jeśli próbujesz użyć tego w swoim przypadku testowym, upewnij się, że używasz zależy od. Na przykład w tym przypadku

Jeśli używasz go dla swojej głównej klasy, lepiej ustaw tę właściwość za pomocą pliku pom.xml jako

<systemProperty>
    <name>deployment.env</name>
    <value>dev</value>
</systemProperty>
Atit Shah
źródło
1

Możesz wspomnieć o atrybutach zmiennych w pliku właściwości i zdefiniować pliki właściwości specyficzne dla środowiska, takie jak local.properties, production.propertied itp.

Teraz, w oparciu o środowisko, jeden z tych plików właściwości może zostać odczytany w jednym z detektorów wywoływanych podczas uruchamiania, takim jak ServletContextListener.

Plik właściwości będzie zawierał wartości specyficzne dla środowiska dla różnych kluczy.

Przykład „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

Przykładowy plik „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

Aby skorzystać z tych plików właściwości, możesz skorzystać z REsource, jak wspomniano poniżej

        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 można zdefiniować jako zmienną środowiskową z odpowiednimi wartościami dla środowiska lokalnego i produkcyjnego.

Po wprowadzeniu tych zmian plik appplicationContext.xml będzie miał następujące zmiany

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

Mam nadzieję że to pomoże .

Sunil
źródło
1

Dzięki @Yiling. To była wskazówka.

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

Następnie powinieneś mieć jedną zmienną środowiskową o nazwie „FILE_PATH”. Upewnij się, że uruchomiłeś ponownie terminal / IDE po utworzeniu tej zmiennej środowiskowej.

Jaikrat
źródło