簡體   English   中英

如何以編程方式覆蓋 Spring Boot application.properties?

[英]How can I override Spring Boot application.properties programmatically?

我有 jdbc 屬性文件,我從外部配置 Web 服務中獲取在 spring 引導中,為了設置 mysql 道具,將它們添加到 application.properties 很容易:

spring.datasource.url=jdbc:mysql://localhost/mydb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

我怎么能在我的應用程序中覆蓋那些程序?

Spring-batch 道具也是如此:

database.driver=com.mysql.jdbc.Driver
database.url=jdbc:mysql://localhost/mydv
database.username=root
database.password=root

您可以在對 ApplicationEnvironmentPrepared 事件做出反應的生命周期偵聽器中添加其他屬性源。

類似的東西:

public class DatabasePropertiesListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
  public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
    ConfigurableEnvironment environment = event.getEnvironment();
    Properties props = new Properties();
    props.put("spring.datasource.url", "<my value>");
    environment.getPropertySources().addFirst(new PropertiesPropertySource("myProps", props));
  }
}

然后在 src/main/resources/META-INF/spring.factories 中注冊該類:

org.springframework.context.ApplicationListener=my.package.DatabasePropertiesListener

這對我有用,但是,由於在應用程序啟動階段還很早,您此時可以做的事情受到了一定的限制,您必須找到一種方法來獲得所需的值,而無需依賴其他彈簧豆類等

只是為了為此線程提供另一個選項以供參考,因為當我開始為我的要求尋找答案時,這在搜索列表中名列前茅,但沒有涵蓋我的用例。

我希望在啟動時以編程方式設置 spring 引導屬性,但不需要使用 spring 支持的不同 XML/配置文件。

最簡單的方法是在定義 SpringApplication 時設置屬性。 下面的基本示例將 tomcat 端口設置為 9999。

@SpringBootApplication
public class Demo40Application{

    public static void main(String[] args){
        SpringApplication application = new SpringApplication(Demo40Application.class);

        Properties properties = new Properties();
        properties.put("server.port", 9999);
        application.setDefaultProperties(properties);

        application.run(args);
    }
}

從 Spring Boot 2.0.X 開始,您可以使用自定義 ApplicationContextInitializer 和 ContextConfiguration 注釋的組合動態覆蓋單個屬性(例如,在單元測試中)。

import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.PortTest.RandomPortInitailizer;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.support.TestPropertySourceUtils;
import org.springframework.util.SocketUtils;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(initializers = RandomPortInitializer.class)
public class PortTest {
    @Autowired
    private SomeService service;

    @Test
    public void testName() throws Exception {
        System.out.println(this.service);
        assertThat(this.service.toString()).containsOnlyDigits();
    }

    @Configuration
    static class MyConfig {

        @Bean
        public SomeService someService(@Value("${my.random.port}") int port) {
            return new SomeService(port);
        }
    }

    static class SomeService {
        private final int port;

        public SomeService(int port) {
            this.port = port;
        }

        @Override
        public String toString() {
            return String.valueOf(this.port);
        }
    }

    public static class RandomPortInitializer
            implements ApplicationContextInitializer<ConfigurableApplicationContext> {

        @Override
        public void initialize(ConfigurableApplicationContext applicationContext) {
            int randomPort = SocketUtils.findAvailableTcpPort();
            TestPropertySourceUtils.addInlinedPropertiesToEnvironment(applicationContext,
                    "my.random.port=" + randomPort);
        }
    }
}

如果您正在運行 Spring Boot 應用程序,這就是在啟動期間設置屬性的方法。

最簡單的方法是在啟動應用程序之前設置屬性。

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Application.class);
        ConfigurableEnvironment env = new ConfigurableEnvironment();
        env.setActiveProfiles("whatever");

        Properties properties = new Properties();
        properties.put("server.port", 9999);
        env.getPropertySources()
            .addFirst(new PropertiesPropertySource("initProps", properties));

        application.setEnvironment(env);
        application.run(args);
    }
}

這可能非常簡單:

@SpringBootApplication
public class SampleApplication {

  public static void main(String[] args) {
    new SpringApplicationBuilder(SampleApplication.class)
        .properties(props())
        .build()
        .run(args);
  }

  private static Properties props() {
    Properties properties = new Properties();
    properties.setProperty("MY_VAR", "IT WORKS");
    return properties;
  }
}

應用程序.yml

test:
  prop: ${MY_VAR:default_value}

如果您出於測試目的需要這樣做:從 spring-test 5.2.5 開始,您可以使用@DynamicPropertySource

    @DynamicPropertySource
    static void setDynamicProperties(DynamicPropertyRegistry registry) {
        registry.add("some.property", () -> some.way().of(supplying).a(value) );
    }

優先於幾乎所有其他提供屬性的方式。 該方法必須是靜態的。

在您的配置中使用此方法,您可以設置默認屬性。

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class)
              .properties("propertyKey=propertyValue");
}

如果需要,您可以通過這種方式以編程方式覆蓋 application.properties。

public static void main(String[] args) {
    SpringApplication app = new SpringApplication(Restdemo1Application.class);
    app.setAdditionalProfiles("dev"); 
    // overrides "application.properties" with  "application-dev.properties"
    app.run(args);

}

將字符串添加到您的應用程序 class

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        System.setProperty("spring.config.location",
                "file:///D:/SpringProjects/SpringBootApp/application.properties");

        SpringApplication.run(Application.class, args);
    }

}

在 META-INF 文件夾下准確創建此文件夾和文件: spring>batch>override>data-source-context.xml 並在您的 xml 文件中確保覆蓋您想要的參數,如下所示:

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${loader.jdbc.driver}" />
    <property name="url" value="${loader.jdbc.url}" />
    <property name="username" value="${loader.jdbc.username}" />
    <property name="password" value="${loader.jdbc.password}" />
</bean>

<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

或者在 xml 文件中使用這樣的 jndi 來訪問你的外部配置文件,比如 catalina.properties

<jee:jndi-lookup id="dataSource"
    jndi-name="java:comp/env/jdbc/loader-batch-dataSource" lookup-on-startup="true"
    resource-ref="true" cache="true" />

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM