Spring Boot: Use database and application.properties for configuration

后端 未结 7 1491
无人及你
无人及你 2020-12-29 15:52

I need to save the configuration of the Spring Boot application in the database.

Is it possible to store the database information in the application.properties

7条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-29 16:13

    Another option is to use ApplicationContextInitializer, with the advantage of being able to use @Value directly and also being able to contract the precedence of the properties.

    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.sql.DataSource;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
    import org.springframework.context.ApplicationContextInitializer;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.core.env.ConfigurableEnvironment;
    import org.springframework.core.env.MapPropertySource;
    import org.springframework.core.env.MutablePropertySources;
    import org.springframework.core.env.PropertySource;
    
    public class ReadDBPropertiesInitializer implements ApplicationContextInitializer {
    
        private static final Logger LOG = LoggerFactory.getLogger(ReadDBPropertiesInitializer.class);
    
        /**
         * Name of the custom property source added by this post processor class
         */
        private static final String PROPERTY_SOURCE_NAME = "databaseProperties";
    
        @Override
        public void initialize(ConfigurableApplicationContext applicationContext) {
    
            ConfigurableEnvironment configEnv = ((ConfigurableEnvironment) applicationContext.getEnvironment());
    
            LOG.info("Load properties from database");
    
            Map propertySource = new HashMap<>();
    
            try {
    
                final String url = getEnv(configEnv, "spring.datasource.url");
    
                String driverClassName = getProperty(configEnv, "spring.datasource.driver-class-name");
    
                final String username = getEnv(configEnv, "spring.datasource.username");
                final String password = getEnv(configEnv, "spring.datasource.password");
    
                DataSource ds = DataSourceBuilder.create().url(url).username(username).password(password)
                        .driverClassName(driverClassName).build();
    
                // Fetch all properties
                PreparedStatement preparedStatement = ds.getConnection()
                        .prepareStatement("SELECT config_key as name, config_value as value, config_label as label FROM TB_CONFIGURATION");
    
                ResultSet rs = preparedStatement.executeQuery();
    
                // Populate all properties into the property source
                while (rs.next()) {             
                    final String propName = rs.getString("name");
                    final String propValue = rs.getString("value");
                    final String propLabel = rs.getString("label");
                    LOG.info(String.format("Property: %s | Label: %s", propName, propLabel));
                    LOG.info(String.format("Value: %s", propValue));
                    propertySource.put(propName, propValue);
                }
    
                // Create a custom property source with the highest precedence and add it to
                // Spring Environment
                applicationContext.getEnvironment().getPropertySources()
                        .addFirst(new MapPropertySource(PROPERTY_SOURCE_NAME, propertySource));
    
            } catch (Exception e) {
                throw new RuntimeException("Error fetching properties from db");
            }
    
        }
    
        private String getEnv(ConfigurableEnvironment configEnv, final String property) {
            MutablePropertySources propertySources = configEnv.getPropertySources();
            PropertySource appConfigProp = propertySources.get("applicationConfigurationProperties");
            return System.getenv().get(((String) appConfigProp.getProperty(property)).replace("${", "").replace("}", ""));
        }
    
        private String getProperty(ConfigurableEnvironment configEnv, final String property) {
            MutablePropertySources propertySources = configEnv.getPropertySources();
            PropertySource appConfigProp = propertySources.get("applicationConfigurationProperties");
            return (String) appConfigProp.getProperty(property);
        }
    

    References:

    1. https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-customize-the-environment-or-application-context
    2. https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config

    PS: This code is a mix of others I found on the internet. The credits are entirely from their authors. Sorry for not being able to find their links, there have been many tests until you get them to work. But if you find this similar to some other found out there, you can be sure that this is just a derivation. ;)

    Environment:

    1. Java: OpenJDK Runtime Environment (build 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11)
    2. Spring: 4.3.11
    3. Spring Boot: 1.5.7
    4. Hibernate Core: 5.2.10-Final

提交回复
热议问题