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);
}
}
} // class ReadDbPropertiesPostProcessor end
@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
}
}
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
@Bean
public static PropertySourcesPlaceholderConfigurer dbConfigForVariableResolving(DatabaseConfiguration aDbConfig)
{
var result = new PropertySourcesPlaceholderConfigurer();
var props = ConfigurationConverter.getProperties(aDbConfig);
result.setProperties(props);
return result;
}
5条答案
按热度按时间bt1cpqcv1#
对于那些需要在应用程序启动之前从数据库加载属性,并使这些属性在项目中的任何地方都可以通过@Value访问的人,只需添加此处理器。
在application.properties中,必须存在数据源数据才能连接到数据库。
然后在文件夹META-INF中创建一个名为spring.factories的文件,并在其中放置以下行:
就这样,检索到的属性将在任何地方访问。
83qze16e2#
我认为使用BeanPostProcessor和Binder是个好主意,这样就不需要列出所有想要读取的属性。下面的代码引用了ConfigurationPropertysBindingPostProcessor。
修改Environment中的PropertySources也是可以实现的,实现BeanPostProcessor接口,在创建Bean之前初始化
zsbz8rwp3#
您可以根据自己的需要手动地用数据库值配置bean(这样您就可以利用SpringCDI和 Boot 数据库配置)。
以设置会话超时为例:
然后是用于配置bean的bean定义:
注意:您可以将数据库调用移到
@PostConstruct
方法,以避免为每个会话都调用。4ktjp1zp4#
使用org.apache.commons:commons-configuration2:jar:2.8.0 dependency中的DatabaseConfiguration类可以让生活变得更轻松,结合springboot2.7.3(rsp.spring5.3.22),下面的设置对我来说很有效。
预处理:必须在别处配置DataSource类型的bean。
bean DatabaseConfiguration能够从DB加载配置值(DB的访问权限在参数aDataSource中配置)。
DB有一个名为"CONFIGURATION"的表。这个表有一个名为"CONFIG_KEY"的列和一个名为"CONFIG_VALUE"的列(当然,表和列可以有你选择的任何名称)。
setApplicationContext方法从上下文中获取上述bean,将配置的值提取为java Properties类,并将这些值转换为可添加到环境中的PropertysPropertySource。
事件监听器onAppStart只是为了证明这样的DB配置值可以从环境中获取。
请注意,将属性添加到spring的环境中并不足以解析属性占位符(例如,在@Value注解的成员中)。要实现这一点,您必须再提供一个bean:
biswetbf5#
对@Maya的回答做一点补充,当你在你的spring Boot 应用程序中使用多个配置文件(例如dev,prd)时,你需要检查
environment.getActiveProfile().length > 0
。我不知道为什么spring调用我的后处理器两次,一次使用配置文件,所以我的最终代码如下: