Spring Boot:从数据库中检索配置

Posted

技术标签:

【中文标题】Spring Boot:从数据库中检索配置【英文标题】:Spring Boot: Retrieving configuration from a database 【发布时间】:2015-07-24 14:40:36 【问题描述】:

谁能给我一些指导,告诉我实现这一目标的最佳方式。

我想扩展 Spring Boot Externalized Configuration 以便我有一个可以从我的应用程序的任何位置调用的方法。此方法将使用键检索属性值。此方法将首先查询一个数据库表,如果它没有找到指定的键,它将回退到 1 中描述的 PropertySource 顺序。

所以我会有类似的服务:

@Service
public class ConfigurationService 

    private final ConfigurationRepository configurationRepository;

    @Autowired
    public ConfigurationService(ConfigurationRepository configurationRepository) 
        this.configurationRepository = configurationRepository;
    

    public String getValue(String key) 
        Configuration configuration = configurationRepository.findOne(key);

        // Add something here to get the property from application.properties if the key does not exist in the db

        return configuration == null ? null : configuration.getValue();
    


我可以使用如下:

foo = configuration.getValue("my.property");

有没有更好的方法来解决这个问题?我是否缺少可以使用的 Spring Boot 功能?

编辑:我希望能够在应用程序运行时更改属性值并获取这些新值。

【问题讨论】:

根据您的项目/部署的规模,这听起来像是 Spring Cloud Config 的潜在案例。 写一个由数据库支持的PropertySource,这样它就可以与系统的其余部分集成。或者简单地编写一个ApplicationInitializer,它从数据库中加载所有属性,将它们包装在PropertiesPropertySource 中并将它们添加到环境中。至少您不想在要与默认机制集成的整个地方调用此方法。 如何使用与数据库链接的缓存来存储键值对 我认为由数据库支持的PropertySource 是我所需要的。如何确保在 application.properties 等之前考虑这一点。 将它放在另一个 PropertySources 的顶部或您想要的位置。 【参考方案1】:

我已经使用 EnvironmentPostProcessor spring 特性来做到这一点。

你需要像这样创建一个类:

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";
    
    /**
     * 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(USERNAME) // replace with your config
                    .password(PASSWORD) // replace with your config
                    .url(DATASOURCE-URL)// replace with your config
                    .driverClassName(DRIVER) // replace with your config
                    .build();

            // Fetch all properties
            PreparedStatement preparedStatement = ds.getConnection().prepareStatement("SELECT name, value FROM propertyConfig WHERE service = ?");
            preparedStatement.setString(1, APP_NAME);
            
            ResultSet rs = preparedStatement.executeQuery();

            // Populate all properties into the property source
            while (rs.next()) 
                String propName = rs.getString("name");
                propertySource.put(propName, rs.getString("value"));
            
            
            // 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 (Exception e) 
            throw new RuntimeException("Error fetching properties from db");
        
    

由于您需要在春季的早期阶段运行此类,因此您需要创建文件spring.factories 并注册您的环境后处理器。此文件需要位于此处:

src/main/resources/META-INF/spring.factories

在内容中你需要将你的类设置为spring属性:

# Environment Post Processor
org.springframework.boot.env.EnvironmentPostProcessor=com.your.package.ReadDbPropertiesPostProcessor

【讨论】:

什么是 PROPERTY_SOURCE_NAME?在我的情况下,我想将属性添加到默认配置文件:application.properties @user3871754 它是属性源 spring map MapPropertySource 的“键”名称。 Spring boot 在内部处理存储属性源的映射,我正在添加一个新的 addFirst 我不得不将以下位置用于弹簧工厂。 src/main/resources/META-INF/spring-factories

以上是关于Spring Boot:从数据库中检索配置的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Spring Boot 项目中的子子表中检索数据?

如何在 Spring Boot 中使用特定日期范围和聚合从 MongoDB 数据库中检索数据?

如何检索 Vault 属性以在 application.yml 中配置 MongoDB 属性?

如何在 Spring Boot 中从资源服务器中的令牌中提取声明

Spring Boot扩展分析

Spring Boot 自动配置的 Jackson ObjectMapper 默认不用于 WebFlux WebClient