背景:公司的項目很大,往往一個項目父項目下面有很多子項目,每個項目都要在application.properties配置文件中寫很多的配置,后來發現有很多配置信息都是固定的,每個項目都需要取維護就會很麻煩,所以准備采取在數據庫中進行配置,統一管理,有點類似於nacos、阿波羅的服務中的配置文件管理功能,如果用這些插件就需要引入一套新的項目,會比較麻煩,很多功能也用不上,所以就自己寫一個。
思路:其實想一下整體的思路就是在項目完全啟動之前,查詢數據庫,將參數查詢到然后賦值到內存中即可。
代碼如下:項目git地址(https://github.com/1924605670/STUDY_DEMO/tree/master/Config_From_Db_Demo),git上有項目代碼,也有使用樣例
@Configuration @Component public class ConfigBeforeInit { @Autowired private ConfigurableEnvironment environment; @Autowired private SystemConfigService service; @PostConstruct public void initSystemConfig() { // 獲取系統屬性集合 MutablePropertySources propertySources = environment.getPropertySources(); // 從數據庫獲取自定義變量列表 Map<String, String> collect = service.getAllBySystemType().stream().collect(Collectors.toMap(SysConfig::getCode, SysConfig::getValue)); // 將轉換后的列表加入屬性中 Properties properties = new Properties(); properties.putAll(collect); // 將屬性轉換為屬性集合,並指定名稱 PropertiesPropertySource constants = new PropertiesPropertySource("system-config", properties); // 定義尋找屬性的正則,該正則為系統默認屬性集合的前綴 Pattern p = compile("^applicationConfig.*"); // 接收系統默認屬性集合的名稱 String name = null; // 標識是否找到系統默認屬性集合 boolean flag = false; // 遍歷屬性集合 for (PropertySource<?> source : propertySources) { // 正則匹配 匹配到:OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.properties]'} if (p.matcher(source.getName()).matches()) { // 接收名稱 name = source.getName(); // 變更標識 flag = true; break; } } if (flag) { // 找到則將自定義屬性添加到該屬性之后,意思就是以application.properties文件配置為准 如果想要以數據庫配置為准,就修改為 propertySources.addBefore(name, constants) propertySources.addAfter(name, constants); } else { // 沒找到默認添加到最后 propertySources.addFirst(constants); } } }
@Data @Table(name = "sys_config") @Entity public class SysConfig implements Serializable { /** * 主鍵 */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; /** * 參數名 */ @Column private String code; /** * 參數值 */ @Column private String value; /** * 配置名稱 */ @Column private String name; /** * 配置描述 */ @Column private String description; /** * 系統類型 */ @Column private String systemType; }
@Repository @Component public interface SystemConfigRepository extends JpaRepository<SysConfig, Long> { List<SysConfig> findAllBySystemTypeIn(List systemType); }
@Service @Component @Slf4j public class SystemConfigService { @Value("#{'${system.types}'.split(',')}") private List<String> types; @Autowired private SystemConfigRepository systemConfigRepository; public List<SysConfig> getAllBySystemType() { List<SysConfig> configs = systemConfigRepository.findAllBySystemTypeIn(types); log.info("加載數據庫系統{},配置文件: {} ", types, configs); return configs; } }