背景:公司的項目很大,往往一個項目父項目下面有很多子項目,每個項目都要在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;
}
}
