# DDK-动态字典键 **Repository Path**: loopstack/ddk ## Basic Information - **Project Name**: DDK-动态字典键 - **Description**: DDK(Dynamic Dictionary Key)动态字典键:对数据进行动态更新处理,接入方只需要接入字典键SDK,即可以完成相关的通知更新功能。 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 6 - **Forks**: 2 - **Created**: 2022-11-29 - **Last Updated**: 2025-06-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: VueBoot, 配置中心, Netty, 分布式应用, AP模型 ## README # DDK-动态字典键 ## 介绍 DDK-动态字典键,接入方只需要接入字典键SDK,即可以完成相关的通知更新功能等 ## 动态字典键是什么 - 分布式动态字典键,就是在一些频繁的配置场景,需要动态加载一些数据,但是又不能在项目中写死,所以需要动态进行加载,所以就有了动态字典键,也可称之为配置中心 ## 常见的字典键 - 比如携程的阿波罗、Spring Cloud Config、Nacos等等,这些本身都实现了一些分布式一致性算法,当然也有一些衍生品,能够支持通知等 - 一些动态字典键是需要依赖第三方组件的,比如携程的阿波罗就依赖了Eureka - 当然了,这也算得上是配置中心了 ## DDK(Dynamic Dictionary Key) - 动态字典键此处设计与与规则引擎的通知更新类似,在规则引擎的注册中心设计上,我们做的只有一件事情,就是自定义了SPI机制, - 用来在被通知之后进行指定的数据通知工作 那么现实的实现上,我们依旧可以这样设计,但是可以分为多种模式,当满足某个条件,则在进行通知的时候,就触发被标记的方法, - 假设有这样的几个注解@BeforeDdkCall、@DdkCall、@AfterDdkCall、@DdkResource,那么则将其标注在方法中,@BeforeDdkCall表示在执行调用之前需要处理的工作,@DdkCall表示需要调用的方法,@AfterDdkCall表示调用业务后需要执行的方法。这样的话,需要执行什么动作,只需要执行业务代码即可 - 另外一种实现,则是为字段进行赋值,当Spring中的Bean中有@DdkValue()的时候,则会进行值的替代转换。 - 动态字典键做的就是这样的功能 ## 项目模块说明 - ddk-admin:后台管理模块 - ddk-admin-biz:业务模块 - ddk-admin-dal:数据库管理模块 - ddk-admin-views:视图模块 - ddk-admin-web:对前端接口模块 - ddk-common:基础模型、枚举模块、DTO模型 - ddk-client:客户端 ## 系统架构设计 - 对于分布式系统来说,每个微服务都有单独的集群,每个集群归属于不同的Docker容器或者物理机,不同的物理机实现异地多活,但是对于不同的项目组或者事业群,则会有不同的服务范围 ![ddk](./doc/img/ddk.png) - 具体的逻辑架构如上,对于不同的服务在不同的机房有不同的集群。那么我们在表设计的时候,就将其设计为以事业群为最高维度, - 事业群下有多个项目组,每个项目组有多个微服务,每个微服务有多个集群。那么大致上页面和表接口就可以设计出来了 ## 设计要点 - 表结构设计,分为配置数据和日志数据;目前配置数据都写在MySQL,都是配置数据,但是为啥规则引擎使用MongoDB呢? - 这个原因之前都说过,因为规则的配置是无限的,在策略的部分可能配置的会很多层级,使用MySQL不方便存储,因此使用MongoDB, - 但是动态字典键的数据,都是平铺数据,不存在大量的动态可扩展的配置,因此使用MySQL;然后操作日志也写在MySQL,不再过多引入相关的技术点了 - 分布式雪花ID,基于Hutool的工具实现 - 此动态字典键&配置中心的设计,基于AP模型。只要有一个服务端可用,那么整体就是可用的 - 在实际的业务开发中,可能这种通知不仅仅在项目中实现,也会在业务方定制的SDK中使用,那么这种情况,就需要考虑同一个项目使用多个SDK的问题,是否需要限制多个SDK的启动?但是实际上项目在启动的时候,所有配置都是基于SpringBean实现的 - 但是有时候我们需要这种配置:某个配置或者通知需要在多个项目中使用,其本质上是一个一对多的数据,这种就需要单独进行处理 - 对于DDK-Client的设计,其在应用启动的时候主动向注册中心进行注册自身,并且定时续约(探活)、注册成功之后,会加载当前作用域(项目唯一标识)的数据到缓存,然后并将其注入到Spring的Bean中,并且在项目启动之后,会自动调用方法进行处理,并且将Bean缓存到Local Cache中 - 对于通知配置,Admin提供了通知接口。在请求达到的时候,会进行发送处理,其实就是发布。 ## 技术与架构选型 - 存储技术选型:MySQL - 开发框架:SpringBoot 2.2.2.RELEASE、Vue2.0、Netty4.x、Vue-Template-Admin - 数据请求:Hutool HttpClient;超时与重试,基于线程池和FutureTask实现 - 分布式锁实现:基于MySQL实现 ## 动态字典键&注册中心要素 ### 事业群 - 事业群是最高平级维度,一个公司可能有多个事业部 ### 项目组 - 一个事业群下有多个项目组 ### 项目 - 一个项目组有多个项目:项目的标识是唯一的 ### 项目配置 - 在一个项目中有多个配置 ### 通知配置 - 一个通知配置对应多个项目组 ## 数据表设计 - 数据表设计,根据动态字典键&注册中心要素可以发现聚合了5张表,有些数据是固化的,每5张表数据都有的,如下表,因此这些字段不再单独列出,具体的可在存储的数据结构中看到 | **字段名称** | **类型** | **备注** | | --- | --- | --- | | id | bigint(20) | mysql 自增主键 | | uuid | varchar(40) | 雪花算法随机UUID | | desc | varchar(80) | 功能描述 | | create_time | datetime | 创建时间 | | update_time | datetime | 更新时间 | | is_delete | int(11) | 状态 状态 1删除,0未删除 | | env | varchar(16) | 环境 | ### 事业群 - 表名字:ddk_group | **字段名称** | **类型** | **备注** | | --- | --- | --- | | group_id | varchar(40) | 事业群组id,唯一| | group_name | varchar(80)| 组名字 | ### 项目组 - 表名字:ddk_team | **字段名称** | **类型** | **备注** | | --- | --- | --- | | team_id | varchar(40) | 项目组id,唯一| | team_name | varchar(80)| 项目组名字 | | group_uuid | varchar(40)| 事业群关联uuid | ### 项目 - 表名字:ddk_app | **字段名称** | **类型** | **备注** | | --- | --- | --- | | app_id | varchar(40) | 项目id,全局唯一| | app_name | varchar(80)| 项目名字 | | team_uuid | varchar(40)| 项目组关联uuid | ### 项目配置 - 表名字:ddk_app_config | **字段名称** | **类型** | **备注** | | --- | --- | --- | | app_config_name | varchar(40) | 配置名称| | app_config_value | varchar(200)| 配置值, | | app_config_type | varchar(16)| 配置类型 | | app_uuid | varchar(40)| 项目关联uuid | ### 通知配置 - 表名字:ddk_notice_config - 当资源存在并且项目拥有权限的时候,则不能发起 | **字段名称** | **类型** | **备注** | | --- | --- | --- | | notice_config_name | varchar(40) | 通知配置名称| | notice_config_resource | varchar(200)| 通知配置资源 | | notice_value | varchar(200)| 测试配置值;因为可能通过配置值进行特殊处理 | | app_uuid | varchar(40)| 项目关联uuid,多个数据库记录多条记录 | - 此处的数据配置是离散的,也就是会拆分为多条记录,因此会进行声明式事务进行处理,代码逻辑如下 ```java public class NoticeConfigServiceImpl extends BaseService implements NoticeConfigService { @Override public void save(List newNoticeConfigList, List appUuid) { // 针对集合的需要特殊处理,通过唯一资源进行数据的更新删除插入处理。不根据数据库id if (CollectionUtils.isEmpty(newNoticeConfigList)) { return; } NoticeConfigVO noticeConfig = newNoticeConfigList.iterator().next(); String noticeConfigResource = noticeConfig.getNoticeConfigResource(); List oldNoticeConfigList = noticeConfigMapping.dos2vos(noticeConfigMapper.queryByNoticeConfigResource(noticeConfigResource, getEnv())); Map newMap = newNoticeConfigList.stream().collect(Collectors.toMap(NoticeConfigVO::getAppUuid, x -> x)); Map oldMap = oldNoticeConfigList.stream().collect(Collectors.toMap(NoticeConfigVO::getAppUuid, x -> x)); // 全部 appUuid Set uuids = Sets.newHashSet(appUuid); uuids.addAll(oldNoticeConfigList.stream().map(NoticeConfigVO::getAppUuid).collect(Collectors.toList())); final ExceptionHolder holder = new ExceptionHolder(); // 使用声明式事务 transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { try { for (String uuid : uuids) { // 数据库有,但是新的vo没有,删除 if (oldMap.get(uuid) != null && newMap.get(uuid) == null) { noticeConfigMapper.delete(oldMap.get(uuid).getId()); } // 数据库有,新的vo也有,更新 if (oldMap.get(uuid) != null && newMap.get(uuid) != null) { NoticeConfigVO noticeConfigVO = newMap.get(uuid); beforeUpdate(noticeConfigVO); noticeConfigMapper.update(noticeConfigMapping.vo2do(noticeConfigVO)); } // 数据库没有,则插入 if (oldMap.get(uuid) == null && newMap.get(uuid) != null) { NoticeConfigVO noticeConfigVO = newMap.get(uuid); beforeInsert(noticeConfigVO); noticeConfigMapper.insert(noticeConfigMapping.vo2do(noticeConfigVO)); } // 数据库没有,并且新的vo也没有 无需操作 这种情况不可能出现~~~ // no op } } catch (Exception e) { logger.error("[NoticeConfigService][save] 保存异常,事务回滚"); status.setRollbackOnly(); holder.setException(e); } } }); if (holder.getException() != null) { throw new RuntimeException(holder.getException()); } } } ``` ## 日志设计 - 表名字:ddk_log | **字段名称** | **类型** | **备注** | | --- | --- | --- | | id | bigint(20) | 主键| | module | varchar(40)| 操作模块 | | target_id | varchar(40)| 对象编号,取uuid| | operator_type | varchar(40)|操作类型 | | content | text|操作数据 | | create_time | datetime|创建时间 | | env | varchar(16)|操作环境 | ## 注册中心设计 - 为什么需要注册中心,因为SDK是在客户端使用,如果需要动态变更数据,那么就需要能够通知到相应的SDK进行数据变更,在规则引擎中,没有使用第三方的注册中心实现,所有就有自己进行编写注册中心 - 总体逻辑比较简单,在SDK所在的客户端启动的时候,会主动将自身的服务ip、服务端口、应用信息等发送给Admin(注册中心),然后注册中心会对这些数据进行注册,写到注册表中进行物理维护,并且定时触发心跳,判断SDK客户端是否还在线,并且维护状态 - 而当需要数据更新的时候,则需要触发消息通知,就会对注册中心的注册信息进行轮询,然后进行服务通知,相关的数据交互,参见架构设计 - 因为SDK Client的接入,会缓存数据,因此在客户端进行发布的时候,可以进行选择部分发布,或者全量发布,在发布之后,各个客户端自行处理数据,此处处理数据需要进行加锁! - `注册表` 设计如下 | **字段名称** | **类型** | **备注** | | --- | --- | --- | | id | bigint(20) | mysql 自增主键 | | uuid | varchar(40) | 雪花算法随机UUID | | desc | varchar(80) | 功能描述 | | create_time | datetime | 创建时间 | | update_time | datetime | 更新时间 | | is_delete | int(11) | 状态 1有效,0无效 | | env | String | 环境 | | client_address | varchar(40) | SDK 服务ip地址 | | client_port | int(11) | SDK 服务端口 | | app_id | varchar(40) | SDK 服务服务名字 | | register_time | datetime | 服务注册时间 | | last_update_time | datetime | 上次注册更新时间 | ## SQL 语句 ```sql /* Navicat Premium Data Transfer Source Server : local Source Server Type : MySQL Source Server Version : 50731 Source Host : localhost:3306 Source Schema : ddk Target Server Type : MySQL Target Server Version : 50731 File Encoding : 65001 Date: 14/01/2023 17:29:16 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for ddk_app -- ---------------------------- DROP TABLE IF EXISTS `ddk_app`; CREATE TABLE `ddk_app` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `uuid` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '雪花算法随机UUID', `desc` varchar(80) COLLATE utf8mb4_bin NOT NULL COMMENT '功能描述', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `is_delete` int(11) NOT NULL COMMENT '状态 1无效,0有效', `env` varchar(16) COLLATE utf8mb4_bin NOT NULL COMMENT '环境', `app_id` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '项目id,全局唯一', `app_name` varchar(80) COLLATE utf8mb4_bin NOT NULL COMMENT '项目名字', `team_uuid` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '项目组关联uuid', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -- ---------------------------- -- Table structure for ddk_app_config -- ---------------------------- DROP TABLE IF EXISTS `ddk_app_config`; CREATE TABLE `ddk_app_config` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `uuid` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '雪花算法随机UUID', `desc` varchar(80) COLLATE utf8mb4_bin NOT NULL COMMENT '功能描述', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `is_delete` int(11) NOT NULL COMMENT '状态 1无效,0有效', `env` varchar(16) COLLATE utf8mb4_bin NOT NULL COMMENT '环境', `app_config_name` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '配置名称', `app_config_value` varchar(200) COLLATE utf8mb4_bin NOT NULL COMMENT '配置值,', `app_config_type` varchar(16) COLLATE utf8mb4_bin NOT NULL COMMENT '配置类型', `app_uuid` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '项目关联uuid', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -- ---------------------------- -- Table structure for ddk_group -- ---------------------------- DROP TABLE IF EXISTS `ddk_group`; CREATE TABLE `ddk_group` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `group_id` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '事业群组id,唯一', `group_name` varchar(80) COLLATE utf8mb4_bin NOT NULL COMMENT '组名字', `uuid` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '雪花算法随机UUID', `desc` varchar(80) COLLATE utf8mb4_bin NOT NULL COMMENT '功能描述', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `is_delete` int(11) NOT NULL COMMENT '状态 1无效,0有效', `env` varchar(16) COLLATE utf8mb4_bin NOT NULL COMMENT '环境', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -- ---------------------------- -- Table structure for ddk_lock -- ---------------------------- DROP TABLE IF EXISTS `ddk_lock`; CREATE TABLE `ddk_lock` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `resource` varchar(200) NOT NULL COMMENT '锁定的资源', `desc` varchar(200) NOT NULL DEFAULT '' COMMENT '描述', `create_time` datetime NOT NULL COMMENT '创建时间', `env` varchar(16) NOT NULL COMMENT '环境', PRIMARY KEY (`id`), UNIQUE KEY `uiq_idx_resource` (`resource`) ) ENGINE=InnoDB AUTO_INCREMENT=667 DEFAULT CHARSET=utf8mb4 COMMENT='数据库分布式锁表'; -- ---------------------------- -- Table structure for ddk_log -- ---------------------------- DROP TABLE IF EXISTS `ddk_log`; CREATE TABLE `ddk_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `module` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '模块', `target_id` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '对象编号,取uuid', `operator_type` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '操作类型', `content` text COLLATE utf8mb4_bin NOT NULL COMMENT '操作数据', `create_time` datetime NOT NULL COMMENT '创建时间', `env` varchar(16) COLLATE utf8mb4_bin NOT NULL COMMENT '操作环境', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -- ---------------------------- -- Table structure for ddk_notice_config -- ---------------------------- DROP TABLE IF EXISTS `ddk_notice_config`; CREATE TABLE `ddk_notice_config` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `uuid` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '雪花算法随机UUID', `desc` varchar(80) COLLATE utf8mb4_bin NOT NULL COMMENT '功能描述', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `is_delete` int(11) NOT NULL COMMENT '状态 1无效,0有效', `env` varchar(16) COLLATE utf8mb4_bin NOT NULL COMMENT '环境', `notice_config_name` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '通知配置名称', `notice_config_resource` varchar(200) COLLATE utf8mb4_bin NOT NULL COMMENT '通知配置资源', `notice_value` varchar(200) COLLATE utf8mb4_bin NOT NULL COMMENT '测试配置值,因为可能通过配置值进行特殊处理', `app_uuid` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '项目关联uuid,多个则会有多条记录', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -- ---------------------------- -- Table structure for ddk_register -- ---------------------------- DROP TABLE IF EXISTS `ddk_register`; CREATE TABLE `ddk_register` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `uuid` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '雪花算法随机UUID', `desc` varchar(80) COLLATE utf8mb4_bin NOT NULL COMMENT '功能描述', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `is_delete` int(11) NOT NULL COMMENT '状态 1无效,0有效', `env` varchar(16) COLLATE utf8mb4_bin NOT NULL COMMENT '环境', `client_address` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT 'client 服务ip地址', `client_port` int(11) NOT NULL COMMENT 'client 服务端口', `app_id` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT 'client 服务服务id', `register_time` datetime NOT NULL COMMENT '服务注册时间', `last_update_time` datetime NOT NULL COMMENT '上次注册更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -- ---------------------------- -- Table structure for ddk_team -- ---------------------------- DROP TABLE IF EXISTS `ddk_team`; CREATE TABLE `ddk_team` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `uuid` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '雪花算法随机UUID', `desc` varchar(80) COLLATE utf8mb4_bin NOT NULL COMMENT '功能描述', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `is_delete` int(11) NOT NULL COMMENT '状态 1无效,0有效', `env` varchar(16) COLLATE utf8mb4_bin NOT NULL COMMENT '环境', `team_id` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '项目组id,唯一', `team_name` varchar(80) COLLATE utf8mb4_bin NOT NULL COMMENT '项目组名字', `group_uuid` varchar(40) COLLATE utf8mb4_bin NOT NULL COMMENT '事业群关联uuid', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; SET FOREIGN_KEY_CHECKS = 1; ``` ## 基于MySQL的分布式锁实现 - 为什么需要分布式锁,因为Admin可能集群部署,在上述的Admin线程池中,会定时进行探活,但是实际上探活只需要单独机器触发即可,不需要所有Admin机器都去触发,这样会导致浪费资源,所以需要在探活的地方加分布式锁 - 分布式锁表设计 | **字段名称** | **类型** | **备注** | | --- | --- | --- | | id | bigint(20) | mysql 自增主键 | | resource | varchar(40) | 雪花算法随机UUID | | desc | varchar(200) | 功能描述 | | env | varchar(200) | 环境 | | create_time | datetime | 资源锁定时间 | - 加锁的实现如下,比较简单的实现,一般分布式锁实现都是使用Redis等 ```java @Service public class LockServiceImpl implements LockService { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(LockServiceImpl.class); @Resource private LockMapper lockMapper; private static final int TIMEOUT = 3000; @Override public Long acquire(String key) { // 查询 String env = EnvUtils.getEnv(); LockDO oldLock = lockMapper.queryByResource(key, env); if (oldLock != null) { if (System.currentTimeMillis() - oldLock.getCreateTime().getTime() > TIMEOUT) { release(key, oldLock.getId()); } return null; } try { LockDO lockDO = new LockDO(); lockDO.setResource(key); lockDO.setDesc(key); lockDO.setEnv(env); lockDO.setCreateTime(new Date()); lockMapper.insert(lockDO); return lockDO.getId(); } catch (DuplicateKeyException ex) { LOGGER.warn("[LockService][acquire][DuplicateKeyException] lock acquire error:{}", ThrowableUtil.stackTraceToString(ex)); } catch (Exception ex) { LOGGER.warn("[LockService][acquire][Exception] lock acquire error:{}", ThrowableUtil.stackTraceToString(ex)); } return null; } @Override public boolean release(String key, Long lockId) { return lockMapper.delete(lockId, key, EnvUtils.getEnv()) > 0; } } ``` ## 项目界面 ### 事业群 ![ddk](./doc/img/group.png) ![ddk](./doc/img/group2.png) ### 项目组 ![ddk](./doc/img/team.png) ![ddk](./doc/img/team2.png) ### 项目 ![ddk](./doc/img/app.png) ![ddk](./doc/img/app2.png) ### 项目字典 ![ddk](./doc/img/appConfig.png) ![ddk](./doc/img/appConfig2.png) ### 通知配置 ![ddk](./doc/img/notification.png) ![ddk](./doc/img/notification2.png) ### 注册中心 ![ddk](./doc/img/register.png) ## 安装教程 - 下载 lsi 基础设施( https://gitee.com/loopstack/lsi ),因为基本的组件都抽离出来,在使用本项目之前请先下载,并且install, 命令(mvn clean package install) - 建立数据库ddk - 修改数据库连接 - 将数据表导入到数据库中(doc/sql/ddk.sql),如果需要现成的数据,则使用(doc/sql/ddk_data.sql) - 如果需要开发前端,则将 `admin/admin-views/pom.xml` 中的`前后端分离注释部分` 打开编译即可,命令(mvn clean package install) - 然后在 `admin/admin-views/resources/vueboot` 下启动前端:`npm run dev` 前后端都启动之后,访问:http://localhost:9528 - 如果不需要开发前端,则直接启动项目即可,启动项目访问:http://localhost:9998/#/dashboard - 测试过程,测试项目可以访问:https://gitee.com/loopstack/ddk-sample 在ddk启动之后,再启动测试项目,在测试项目中会有部分的执行日志,启动后观察即可 ## dal 代码生成器 - 因为是MySQL项目,因此使用Mybatis3框架作为DAL访问层框架,因此在LSI基础设施中编写了代码生成器 - 配置文件在 `admin/admin-dal/config/gen.properties` 相关的参数参见注释 - 如果已经修改了配置,那么请不要再使用DAL组件生成,因为会覆盖源文件 - 插件的pom ```xml cn.icanci.loopstack lsi-dalgen-maven-plugin 0.0.0.1-SNAPSHOT config/gen.properties ``` ## 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request