web-dev-qa-db-ja.com

Spring Bootアプリのプロパティをデータベースから読み込む

この問題についてアドバイスをお願いします。SpringBootアプリケーションでは、(cronピリオド、電子メールデータなど)データベースからいくつかのプロパティをロードします。ロードされたデータ。どうすればこれができますか?

10
Maya

アプリケーションが開始する前にデータベースからプロパティをロードする必要があり、プロジェクトの任意の場所で@Valueを使用してこれらの小道具にアクセスできるようにする場合は、このプロセッサを追加するだけです。

public class ReadDbPropertiesPostProcessor implements EnvironmentPostProcessor {
/**
 * Name of the custom property source added by this post processor class
 */
private static final String PROPERTY_SOURCE_NAME = "databaseProperties";

private String[] KEYS = {
        "Excel.threads",
        "cronDelay",
        "cronDelayEmail",
        "spring.mail.username",
        "spring.mail.password",
        "spring.mail.Host",
        "spring.mail.port",
        "spring.mail.properties.mail.transport.protocol",
        "spring.mail.properties.mail.smtp.auth",
        "spring.mail.properties.mail.smtp.starttls.enabled",
        "spring.mail.properties.mail.debug",
        "spring.mail.properties.mail.smtp.starttls.required",
        "spring.mail.properties.mail.socketFactory.port",
        "spring.mail.properties.mail.socketFactory.class",
        "spring.mail.properties.mail.socketFactory.fallback",
        "white.executor.threads",
        "white.search.threads",
        "lot.sync.threads",
        "lot.async.threads",
        "lot.soap.threads",
        "Excel.async.threads",
        "kpi.threads",
        "upload.threads"
};

/**
 * Adds Spring Environment custom logic. This custom logic fetch properties from database and setting highest precedence
 */
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {

    Map<String, Object> propertySource = new HashMap<>();

    try {

        // Build manually datasource to ServiceConfig
        DataSource ds = DataSourceBuilder
                .create()
                .username(environment.getProperty("spring.datasource.username"))
                .password(environment.getProperty("spring.mail.password"))
                .url(environment.getProperty("spring.datasource.url"))
                .driverClassName("com.mysql.jdbc.Driver")
                .build();

        // Fetch all properties

        Connection connection = ds.getConnection();

        JTrace.genLog(LogSeverity.informational, "cargando configuracion de la base de datos");

        PreparedStatement preparedStatement = connection.prepareStatement("SELECT value FROM config WHERE id = ?");

        for (int i = 0; i < KEYS.length; i++) {

            String key = KEYS[i];

            preparedStatement.setString(1, key);

            ResultSet rs = preparedStatement.executeQuery();

            // Populate all properties into the property source
            while (rs.next()) {
                propertySource.put(key, rs.getString("value"));
            }

            rs.close();
            preparedStatement.clearParameters();

        }

        preparedStatement.close();
        connection.close();

        // Create a custom property source with the highest precedence and add it to Spring Environment
        environment.getPropertySources().addFirst(new MapPropertySource(PROPERTY_SOURCE_NAME, propertySource));

    } catch (Throwable e) {
        throw new RuntimeException(e);
    }
}

application.propertiesでは、データベースに接続できるようにするために、データソースデータが存在している必要があります。

次に、フォルダMETA-INFspring.factoriesという名前のファイルを作成し、そこに次の行を追加します。

org.springframework.boot.env.EnvironmentPostProcessor=test.config.ReadDbPropertiesPostProcessor

そして、それだけです。取得したプロパティはどこからでもアクセスできます。

11
Maya

必要に応じて、データベース値を使用してBeanを手動で構成できます(これにより、Spring CDIとブートデータベース構成を利用できます)。

たとえば、セッションタイムアウトを設定します。

@SpringBootApplication
public class MySpringBootApplication extends SpringBootServletInitializer {           
    public static void main(String[] args) {
        SpringApplication.run(MySpringBootApplication.class, args);
    }

    @Bean
    public HttpSessionListener httpSessionListener(){
        return new MyHttpSessionListener();
    }
}

次に、Beanを構成するためのBean定義:

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MyHttpSessionListener implements HttpSessionListener {   
    @Autowired
    private MyRepository myRepository;

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        se.getSession().setMaxInactiveInterval(this.myRepository.getSessionTimeoutSeconds()); 
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        // Noop
    }

}

注:データベース呼び出しを@PostConstructメソッドに移動して、セッションごとに呼び出さないようにすることができます。

2
java-addict301