2015-05-13 104 views
3

任何人都可以爲我提供一些關於實現此目標的最佳方式的指導。Spring Boot:從數據庫檢索配置

我想擴展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功能嗎?

編輯:我希望能夠在應用程序運行時更改屬性的值,並獲取這些新值。

+2

根據項目/部署規模有多大,這聽起來像一個潛在的Spring Cloud配置案例。 – chrylis

+2

編寫一個由數據庫支持的'PropertySource',這樣它就可以與系統的其他部分集成。或者簡單地寫一個'ApplicationInitializer',它加載數據庫中的所有屬性,將它們包裝在一個'PropertiesPropertySource'中並將它們添加到環境中。至少你不想在你想要與默認機制集成的整個地方調用這個方法。 –

+0

如何在數據庫鏈接中使用緩存來存儲鍵值對 – ema

回答

2

我已經使用EnvironmentPostProcessor彈簧功能來做到這一點。

你需要創建一個類是這樣的:

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/META-INF/spring-factories 

在您需要將類設置彈簧屬性的內容:

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

什麼是PROPERTY_SOURCE_NAME?我想在我的情況下將屬性添加到默認配置文件中:application.properties – user3871754

+0

@ user3871754它是屬性源泉映射「MapPropertySource」的「關鍵」名稱。 Spring引導在內部處理一個存儲屬性資源的地圖,我用'addFirst'添加一個新的 –