java 从数据库检索Sping Boot 配置

gab6jxml  于 2022-12-21  发布在  Java
关注(0)|答案(1)|浏览(118)

谁能给我一些指导,告诉我实现这一目标的最佳途径。
我想扩展Sping 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");

有没有更好的方法来处理这件事?我是不是错过了一个我可以利用的春 Boot 功能?
我希望能够在应用程序运行时更改属性的值,并选择这些新值。

i34xakig

i34xakig1#

我已经使用EnvironmentPostProcessorSpring功能来完成此操作。
你需要创建一个类,如下所示:

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 的早期阶段运行这个类,你需要创建文件spring.factories并注册你的环境后处理器。

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

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

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

相关问题