この問題についてアドバイスをお願いします。SpringBootアプリケーションでは、(cronピリオド、電子メールデータなど)データベースからいくつかのプロパティをロードします。ロードされたデータ。どうすればこれができますか?
アプリケーションが開始する前にデータベースからプロパティをロードする必要があり、プロジェクトの任意の場所で@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
そして、それだけです。取得したプロパティはどこからでもアクセスできます。
必要に応じて、データベース値を使用して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
メソッドに移動して、セッションごとに呼び出さないようにすることができます。