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