【问题标题】:how to read System environment variable in Spring applicationContext如何在 Spring applicationContext 中读取系统环境变量
【发布时间】:2011-04-27 07:09:42
【问题描述】:

如何在应用上下文中读取系统环境变量?

我想要类似的东西:

<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

【问题讨论】:

    标签: java spring environment-variables


    【解决方案1】:

    你很接近 :o) Spring 3.0 增加了Spring Expression Language。 你可以使用

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

    结合java ... -Denv=QA应该可以解决你的问题。

    请注意@yiling 的评论:

    为了访问系统环境变量,即OS级别 正如 amoe 所评论的那样,我们可以简单地使用“systemEnvironment” 而不是该 EL 中的“systemProperties”。喜欢 #{systemEnvironment['ENV_VARIABLE_NAME']}

    【讨论】:

    • java ... -Denv=QA 是什么意思?
    • 您设置了一个 java 系统属性值。您可以在 assert System.getProperty("env") == "QA"; 之类的代码中读取此值
    • 我认为这个答案不正确,这不允许读取系统环境变量(即用export 设置的操作系统级变量等),它只允许读取Java 系统属性。
    • -Dprop=... 在命令行中设置 java 属性。您可以通过System.getProperty("prop") 阅读此属性。如果您想阅读操作系统属性,请使用System.getenv("os-env-variable")。请参阅 javadoc:docs.oracle.com/javase/6/docs/api/java/lang/System.html
    • 为了访问系统环境变量,也就是amoe所说的操作系统级别的变量,我们可以在那个EL中简单地使用“systemEnvironment”而不是“systemProperties”。喜欢#{systemEnvironment['ENV_VARIABLE_NAME']}
    【解决方案2】:

    现在可以放

    @Autowired
    private Environment environment;
    

    在你的@Component@Bean等中,然后通过Environment类访问属性:

    environment.getProperty("myProp");
    

    对于单个属性@Bean

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

    另一种方式是方便的@ConfigurationProperties beans:

    @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

    【讨论】:

    • 环境变量是否也可以通过Environment 接口访问?
    • @NikhilSahu 是的,他们是。您可以使用与查询 java.lang.System 时相同的密钥来访问它们,例如要获取操作系统类型,您会使用 env.getProperty("os.name") 假设 env 是您的 org.springframework.core.env.Environment 实例。
    • @Autowired private Environment environment; 不适用于我的Component 环境始终为空
    【解决方案3】:

    检查this article。它通过支持外部属性的PropertyPlaceholderConfigurer(通过systemPropertiesMode 属性)为您提供了几种方法。

    【讨论】:

      【解决方案4】:

      是的,例如,您可以使用&lt;property name="defaultLocale" value="#{ systemProperties['user.region']}"/&gt;

      变量systemProperties是预定义的,见6.4.1 XML based configuration

      【讨论】:

        【解决方案5】:

        在您的 bean 定义中,确保包含“searchSystemEnvironment”并将其设置为“true”。如果您使用它来构建文件路径,请将其指定为 file:/// 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>
        

        【讨论】:

          【解决方案6】:

          使用Spring EL可以eis example写如下

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

          【讨论】:

            【解决方案7】:

            对于我的用例,我只需要访问系统属性,但提供默认值以防它们未定义。

            这就是你的做法:

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

            【讨论】:

              【解决方案8】:

              如下声明属性占位符

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

              然后假设您想为您的 Tomcat bean 或任何 bean 读取 System.property("java.io.tmpdir"),然后在您的属性文件中添加以下内容:

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

              【讨论】:

                【解决方案9】:

                这就是你的做法:

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

                但请记住,spring 会先加载,然后再加载这个 bean MethodInvokingFactoryBean。因此,如果您尝试将其用于您的测试用例,请确保您使用依赖项。例如在这种情况下

                如果你将它用于你的主类,最好使用你的 pom.xml 来设置这个属性

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

                【讨论】:

                  【解决方案10】:

                  您可以在属性文件中提及您的变量属性,并定义特定于环境的属性文件,如 local.properties、production.properied 等。

                  现在根据环境,这些属性文件之一可以在启动时调用的侦听器中读取,例如 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
                  

                  要使用这些属性文件,您可以使用下面提到的资源

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

                  希望这会有所帮助。

                  【讨论】:

                    【解决方案11】:

                    感谢@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。

                    【讨论】:

                      【解决方案12】:

                      更新版本(2020 年)。

                      使用System.getenv("ENV_VARIABLE")

                      【讨论】:

                      • getenv(小写)
                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-08-10
                      • 1970-01-01
                      • 2015-08-29
                      • 2022-07-29
                      • 1970-01-01
                      • 1970-01-01
                      • 2017-12-01
                      相关资源
                      最近更新 更多