在一次开发中,领导提供了一个需求,将springboot配置文件的值存放在数据库中,并且能否动态更改。在调用后,决定先做了一个初版。
1.实现代码
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.Map; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.origin.OriginTrackedValue; import org.springframework.context.ApplicationListener; import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.PropertySource; public class ConfigureListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> { @Override public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { Connection conn = null; Statement st = null; ResultSet rs = null; // 获取spring Environment MutablePropertySources propertySources = event.getEnvironment().getPropertySources(); // 配置放在了application-pro或者是application-dev 中 赋值复制需要在其中赋值 for (PropertySource<?> propertySource : propertySources) { boolean applicationConfig = propertySource.getName().contains("application-"); if (!applicationConfig) { continue; } // 获取上文的application集合中获取数据库连接 Map<String, OriginTrackedValue> dataBaseSource = (Map<String, OriginTrackedValue>)propertySource.getSource(); String driverClass = String.valueOf(dataBaseSource.get("spring.datasource.driver-class-name").getValue()); String url = String.valueOf(dataBaseSource.get("spring.datasource.url").getValue()); String user = String.valueOf(dataBaseSource.get("spring.datasource.username").getValue()); String password = String.valueOf(dataBaseSource.get("spring.datasource.password").getValue()); // 因为在spring初始化之前 所有不能使用注解 所以需要jdbc直接连接数据库 首先建立驱动 try { Class.forName("oracle.jdbc.driver.OracleDriver"); conn = DriverManager.getConnection(url, user, password); // 1、获取连接对象 // 2、创建statement类对象,用来执行SQL语句!! st = conn.createStatement(); // 3、创建sql查询语句 String sql = "select * from SYS_CONFIGURE"; // 4、执行sql语句并且换回一个查询的结果集 rs = st.executeQuery(sql); while (rs.next()) { // 获取数据库中的数据 String item = rs.getString("ITEM"); String itemValue = rs.getString("ITEM_VALUE"); // 通过数据库中的配置 修改application集合中数据 Map<String, OriginTrackedValue> source = (Map<String, OriginTrackedValue>)propertySource.getSource(); OriginTrackedValue originTrackedValue = source.get(item); OriginTrackedValue newOriginTrackedValue = OriginTrackedValue.of(itemValue, originTrackedValue.getOrigin()); source.put(item, newOriginTrackedValue); } } catch (Exception e) { e.printStackTrace(); } } } }
@SpringBootApplication public class TestApplication { public static void main(String[] args) { SpringApplication app = new SpringApplication(TestApplication.class); app.addListeners(new ConfigureListener()); app.run(args); } }
2.原理简介
在springboot初始化时,会识别application .xml,并将扫描到的配置类放于MutablePropertySources中,在执行初始化后,将会执行addListeners,在addListeners中重新复写了MutablePropertySources对象。将从数据库中查询到的配置覆盖到已经查询到的对象中,从而实现配置文件的更改。
获取MutablePropertySources 代码。 MutablePropertySources propertySources = event.getEnvironment().getPropertySources();
3.使用中间件
最后该方案只是做了一个demo。建议使用apollo或者nacos作为配置中心。功能更加的强大且更为稳定。何苦自己造轮子呢。。。