SpringBoot统一属性配置,以数据库作为配置中心
共 8766字,需浏览 18分钟
·
2024-07-25 07:22
阅读本文大概需要 5 分钟。
来自:juejin.cn/post/7332708703400312873
引言
杂乱的属性配置
SpringBoot 属性配置文件
、数据库配置表
以及硬编码属性字段
。
SpringBoot 属性配置文件
# 阿里云
aliyun.accessKeyId=LT***uao
aliyun.accessKeySecret=0Qhe***byr1f
数据库配置表
硬编码属性字段
public class WechatConfig {
public static final class MINI {
public static final String APP_ID = "wx2***dd5";
public static final String APP_SECRET = "38f***9c74";
}
}
配置分离方案
属性配置归类
-
第一种是 Spring 配置,比如Spring的 server.prot
,Mybatis的mybatis.mapper-locations
,即属于框架层面的,这种规定要配置在application[-ENV].properties
; -
第二种是服务配置,比如定义的日志配置 logback-spring.xml
及配置logging.path
,规定按原本方式单独配置; -
最后是第三方平台配置,比如阿里云OSS、微信小程序,规定使用数据库作为配置中心。
数据表设计
-
字段 data_key
和data_value
作为单项配置的键值对,其含义等同于Spring中的properties; -
字段 data_group
作为配置项的分组,例如对阿里云 OSS 的组名为aliyun.oss
; -
字段 namespace
为命令空间的含义,可以作为区分环境用,或者分租户。
CREATE TABLE `admin_data_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`create_time` bigint(20) DEFAULT '0' COMMENT '创建时间',
`create_user` bigint(20) DEFAULT '0' COMMENT '创建者',
`update_time` bigint(20) DEFAULT '0' COMMENT '更新时间',
`update_user` bigint(20) DEFAULT '0' COMMENT '更新者',
`is_del` tinyint(4) DEFAULT '0' COMMENT '是否删除:1.是 0.否',
`data_key` varchar(100) DEFAULT '' COMMENT '键',
`data_value` varchar(100) DEFAULT '' COMMENT '值',
`description` varchar(50) DEFAULT '' COMMENT '描述',
`data_group` varchar(50) DEFAULT 'default_group' COMMENT '分组',
`namespace` varchar(50) DEFAULT 'public' COMMENT '命名空间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='配置中心';
编码实现
核心配置类
@PostConstruct
注解的init读取数据库数据配置,将读取到的数据配置作为MapPropertySource
类型的数据源,之后将MapPropertySource
放置到MutablePropertySources
首位 (addFirst),作为最高优先级配置。
@Configuration
public class DBPropertyDataConfig {
@Resource
private ConfigurableEnvironment configurableEnvironment;
@Resource
private AdminDataConfigMapper adminDataConfigMapper;
@PostConstruct
public void init() {
MutablePropertySources mutablePropertySources = configurableEnvironment.getPropertySources();
List<AdminDataConfig> dataConfigList = adminDataConfigMapper.list(null);
if (dataConfigList == null || dataConfigList.size() == 0) {
return;
}
Map<String, Object> propertyMap = dataConfigList.stream()
.collect(Collectors.toMap(AdminDataConfig::getDataKey, AdminDataConfig::getDataValue));
MapPropertySource mapPropertySource = new MapPropertySource("db_data_config", propertyMap);
mutablePropertySources.addFirst(mapPropertySource);
}
}
数据注入
setter
方法添加@Value
注解使配置注入;同样地,对于新的属性配置则需要编写新的配置类。
WechatConfig
配置类为例进行改造:
@Configuration
public class WechatConfig {
public static final class MINI {
public static String APP_ID;
public static String APP_SECRET;
}
@Value("${wechat.mini.app-id}")
public void setAppId(String appId) {
MINI.APP_ID = appId;
}
@Value("${wechat.mini.app-secret}")
public void setAppSecret(String appSecret) {
MINI.APP_SECRET = appSecret;
}
}
注意事项
-
成员变量不可使用final声明 -
使用 Congfiguration
将类作为Spring Bean -
static声明的变量注入需要在setter方法上注解 -
不能在内部类执行注入
DBPropertyDataConfig
;例如,BlackBoxFacade
会先于DBPropertyDataConfig
加载,则需要@DependsOn
指定其依赖关系。如下:
@Service
@DependsOn("DBPropertyDataConfig")
public class BlackBoxFacade {
@Value("${black-box.company}")
public String SYS_COMPANY;
}
测试验证
数据准备
INSERT INTO `admin_data_config`
(`data_key`, `data_value`, `description`, `data_group`, `namespace`)
VALUES
('wechat.mini.app-id', 'wx2***', '微信小程序 appid', 'wechat.mini', 'public'),
('wechat.mini.app-secret', '38f***', '微信小程序 app secret', 'wechat.mini', 'public');
接口测试
-
请求URL: http://localhost:8080/app/account/login
-
请求方法: POST
-
Content-Type:form-data
-
请求参数: data : {"jsCode":"FFF"}
断点观测
总结与扩展
推荐阅读:
程序员在线工具站:cxytools.com 推荐一个我自己写的工具站:http://cxytools.com,专为程序员设计,包括时间日期、JSON处理、SQL格式化、随机字符串生成、UUID生成、随机数生成、文本Hash...等功能,提升开发效率。
⬇戳阅读原文直达! 朕已阅