From a9da274da1c757f2de5a804b12441e54ed601fca Mon Sep 17 00:00:00 2001 From: nothingp Date: Sat, 18 Dec 2021 23:55:45 +0800 Subject: [PATCH 1/6] =?UTF-8?q?:hammer:=20=E5=A2=9E=E5=8A=A0=E8=A1=A8?= =?UTF-8?q?=E7=9A=84=E5=AD=97=E7=AC=A6=E9=9B=86=20(#137)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/3ballcat-i18n-0.5.0.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/3ballcat-i18n-0.5.0.sql b/doc/3ballcat-i18n-0.5.0.sql index ff0ec6e1c..356130d06 100644 --- a/doc/3ballcat-i18n-0.5.0.sql +++ b/doc/3ballcat-i18n-0.5.0.sql @@ -12,7 +12,7 @@ CREATE TABLE `i18n_data` ( `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `udx_laguage_tag_code` (`language_tag`,`code`,`deleted`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=93 DEFAULT CHARSET=utf8mb4 COMMENT='国际化信息'; +) ENGINE=InnoDB AUTO_INCREMENT=93 DEFAULT CHARSET=utf8mb4 COLLATE = utf8mb4_general_ci COMMENT='国际化信息'; -- 插入菜单的国际化信息配置 INSERT INTO `i18n_data` (`id`, `language_tag`, `code`, `message`, `remarks`, `create_time`, `update_time`) VALUES (1, 'zh-CN', 'menu.account', '个人页', '', '2021-08-06 11:46:52', NULL); From ebadeb48623286a561082f0850235ac056a16238 Mon Sep 17 00:00:00 2001 From: Hccake Date: Wed, 22 Dec 2021 19:20:53 +0800 Subject: [PATCH 2/6] :arrow_up: up spring-boot 2.6.2 & up springdoc-openapi 1.6.2 --- ballcat-dependencies/pom.xml | 4 ++-- pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ballcat-dependencies/pom.xml b/ballcat-dependencies/pom.xml index 179f9b5d7..66bc61d00 100644 --- a/ballcat-dependencies/pom.xml +++ b/ballcat-dependencies/pom.xml @@ -42,12 +42,12 @@ 1.2.7 0.0.29 - 2.6.1 + 2.6.2 2.3.8.RELEASE 3.0.0 1.5.21 2.1.11 - 1.6.0 + 1.6.2 2.5.0 5.7.16 1.2.76 diff --git a/pom.xml b/pom.xml index 671e79cab..30e0130ad 100644 --- a/pom.xml +++ b/pom.xml @@ -63,7 +63,7 @@ 3.1.0 3.1.1 - 2.6.1 + 2.6.2 1.4.2.Final From 09445b00fbd1c9be421cc55ae321689ef03c2be6 Mon Sep 17 00:00:00 2001 From: Hccake Date: Thu, 23 Dec 2021 11:36:38 +0800 Subject: [PATCH 3/6] =?UTF-8?q?:bug:=20=E8=B0=83=E6=95=B4=20CustomJavaTime?= =?UTF-8?q?Module=20=E7=9A=84=E6=B3=A8=E5=86=8C=E6=96=B9=E5=BC=8F=EF=BC=8C?= =?UTF-8?q?=E9=98=B2=E6=AD=A2=E8=A2=AB=20JSR310=20=E7=9A=84=20JavaTimeModu?= =?UTF-8?q?le=20=E8=A6=86=E7=9B=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...imeModule.java => CustomJavaTimeModule.java} | 4 ++-- .../jackson/CustomJacksonAutoConfiguration.java | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) rename ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/jackson/{JavaTimeModule.java => CustomJavaTimeModule.java} (95%) diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/jackson/JavaTimeModule.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/jackson/CustomJavaTimeModule.java similarity index 95% rename from ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/jackson/JavaTimeModule.java rename to ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/jackson/CustomJavaTimeModule.java index e9be02f80..06196c471 100644 --- a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/jackson/JavaTimeModule.java +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/jackson/CustomJavaTimeModule.java @@ -24,9 +24,9 @@ * @see com.fasterxml.jackson.datatype.jsr310.JavaTimeModule * @author Hccake */ -public class JavaTimeModule extends SimpleModule { +public class CustomJavaTimeModule extends SimpleModule { - public JavaTimeModule() { + public CustomJavaTimeModule() { super(PackageVersion.VERSION); this.addSerializer(LocalDateTime.class, diff --git a/ballcat-starters/ballcat-spring-boot-starter-web/src/main/java/com/hccake/ballcat/autoconfigure/web/jackson/CustomJacksonAutoConfiguration.java b/ballcat-starters/ballcat-spring-boot-starter-web/src/main/java/com/hccake/ballcat/autoconfigure/web/jackson/CustomJacksonAutoConfiguration.java index 1db777561..071fb8402 100644 --- a/ballcat-starters/ballcat-spring-boot-starter-web/src/main/java/com/hccake/ballcat/autoconfigure/web/jackson/CustomJacksonAutoConfiguration.java +++ b/ballcat-starters/ballcat-spring-boot-starter-web/src/main/java/com/hccake/ballcat/autoconfigure/web/jackson/CustomJacksonAutoConfiguration.java @@ -4,11 +4,11 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; -import com.hccake.ballcat.common.core.jackson.JavaTimeModule; +import com.hccake.ballcat.common.core.jackson.CustomJavaTimeModule; import com.hccake.ballcat.common.core.jackson.NullSerializerModifier; import com.hccake.ballcat.common.desensitize.json.DesensitizeStrategy; -import com.hccake.ballcat.common.desensitize.json.JsonDesensitizeSerializerModifier; import com.hccake.ballcat.common.desensitize.json.JsonDesensitizeModule; +import com.hccake.ballcat.common.desensitize.json.JsonDesensitizeSerializerModifier; import com.hccake.ballcat.common.util.json.JacksonJsonToolAdapter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -46,17 +46,24 @@ public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) { // NULL值修改 objectMapper.setSerializerFactory( objectMapper.getSerializerFactory().withSerializerModifier(new NullSerializerModifier())); - // 时间解析器 - objectMapper.registerModule(new JavaTimeModule()); // 有特殊需要转义字符, 不报错 objectMapper.enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature()); - // 更新 JsonUtils 中的 ObjectMapper,保持容器和工具类中的 ObjectMapper 对象一致 JacksonJsonToolAdapter.setMapper(objectMapper); return objectMapper; } + /** + * 注册自定义 的 jackson 时间格式,高优先级,用于覆盖默认的时间格式 + * @return CustomJavaTimeModule + */ + @Bean + @ConditionalOnMissingBean(CustomJavaTimeModule.class) + public CustomJavaTimeModule customJavaTimeModule() { + return new CustomJavaTimeModule(); + } + /** * 注册 Jackson 的脱敏模块 * @return Jackson2ObjectMapperBuilderCustomizer From db0fa77dbf5dd20abaa499fa5dc9b79007747877 Mon Sep 17 00:00:00 2001 From: guide Date: Thu, 23 Dec 2021 17:33:42 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=8E=A8=20=E4=BF=AE=E6=94=B9=20com.ali?= =?UTF-8?q?baba.excel.util.ClassUtils,=E7=A7=BB=E9=99=A4=20bad=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/NotifyInfoDelegateHandler.java | 1 - .../com/alibaba/excel/util/ClassUtils.java | 47 +++++++++---------- .../write/executor/ExcelWriteAddExecutor.java | 4 +- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/ballcat-notify/ballcat-notify-biz/src/main/java/com/hccake/ballcat/notify/handler/NotifyInfoDelegateHandler.java b/ballcat-notify/ballcat-notify-biz/src/main/java/com/hccake/ballcat/notify/handler/NotifyInfoDelegateHandler.java index 5d19e487e..44252b86a 100644 --- a/ballcat-notify/ballcat-notify-biz/src/main/java/com/hccake/ballcat/notify/handler/NotifyInfoDelegateHandler.java +++ b/ballcat-notify/ballcat-notify-biz/src/main/java/com/hccake/ballcat/notify/handler/NotifyInfoDelegateHandler.java @@ -4,7 +4,6 @@ import com.hccake.ballcat.system.model.entity.SysUser; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.Assert; diff --git a/ballcat-starters/ballcat-spring-boot-starter-easyexcel/src/main/java/com/alibaba/excel/util/ClassUtils.java b/ballcat-starters/ballcat-spring-boot-starter-easyexcel/src/main/java/com/alibaba/excel/util/ClassUtils.java index 0bbdc4151..8e88f203f 100644 --- a/ballcat-starters/ballcat-spring-boot-starter-easyexcel/src/main/java/com/alibaba/excel/util/ClassUtils.java +++ b/ballcat-starters/ballcat-spring-boot-starter-easyexcel/src/main/java/com/alibaba/excel/util/ClassUtils.java @@ -21,9 +21,9 @@ **/ public class ClassUtils { - private static final Map> FIELD_CACHE = new ConcurrentHashMap>(); + private static final Map, SoftReference> FIELD_CACHE = new ConcurrentHashMap<>(); - public static void declaredFields(Class clazz, Map sortedAllFiledMap, + public static void declaredFields(Class clazz, Map sortedAllFiledMap, Map indexFiledMap, Map ignoreMap, Boolean convertAllFiled, Boolean needIgnore, Holder holder) { FieldCache fieldCache = getFieldCache(clazz, convertAllFiled); @@ -33,11 +33,11 @@ public static void declaredFields(Class clazz, Map sortedAllFile if (ignoreMap != null) { ignoreMap.putAll(fieldCache.getIgnoreMap()); } - Map tempIndexFildMap = indexFiledMap; - if (tempIndexFildMap == null) { - tempIndexFildMap = new TreeMap(); + Map tempIndexFieldMap = indexFiledMap; + if (tempIndexFieldMap == null) { + tempIndexFieldMap = new TreeMap<>(); } - tempIndexFildMap.putAll(fieldCache.getIndexFiledMap()); + tempIndexFieldMap.putAll(fieldCache.getIndexFiledMap()); Map originSortedAllFiledMap = fieldCache.getSortedAllFiledMap(); if (!needIgnore) { @@ -60,7 +60,7 @@ public static void declaredFields(Class clazz, Map sortedAllFile if (ignoreMap != null && name != null) { ignoreMap.put(name, field); } - tempIndexFildMap.remove(index); + tempIndexFieldMap.remove(index); ignoreNum++; } else if (field != null) { @@ -70,12 +70,12 @@ else if (field != null) { } } - public static void declaredFields(Class clazz, Map sortedAllFiledMap, Boolean convertAllFiled, + public static void declaredFields(Class clazz, Map sortedAllFiledMap, Boolean convertAllFiled, Boolean needIgnore, WriteHolder writeHolder) { declaredFields(clazz, sortedAllFiledMap, null, null, convertAllFiled, needIgnore, writeHolder); } - private static FieldCache getFieldCache(Class clazz, Boolean convertAllFiled) { + private static FieldCache getFieldCache(Class clazz, Boolean convertAllFiled) { if (clazz == null) { return null; } @@ -93,38 +93,39 @@ private static FieldCache getFieldCache(Class clazz, Boolean convertAllFiled) { return FIELD_CACHE.get(clazz).get(); } - private static void declaredFields(Class clazz, Boolean convertAllFiled) { - List tempFieldList = new ArrayList(); - Class tempClass = clazz; + private static void declaredFields(Class clazz, Boolean convertAllFiled) { + List tempFieldList = new ArrayList<>(); + Class tempClass = clazz; // When the parent class is null, it indicates that the parent class (Object // class) has reached the top // level. + // TODO BaseRowModel is Deprecated,you don't need to extend any classes while (tempClass != null && tempClass != BaseRowModel.class) { Collections.addAll(tempFieldList, tempClass.getDeclaredFields()); // Get the parent class and give it to yourself tempClass = tempClass.getSuperclass(); } // Screening of field - Map> orderFiledMap = new TreeMap>(); - Map indexFiledMap = new TreeMap(); - Map ignoreMap = new HashMap(16); + Map> orderFiledMap = new TreeMap<>(); + Map indexFiledMap = new TreeMap<>(); + Map ignoreMap = new HashMap<>(16); - ExcelIgnoreUnannotated excelIgnoreUnannotated = (ExcelIgnoreUnannotated) clazz - .getAnnotation(ExcelIgnoreUnannotated.class); + assert clazz != null; + ExcelIgnoreUnannotated excelIgnoreUnannotated = clazz.getAnnotation(ExcelIgnoreUnannotated.class); for (Field field : tempFieldList) { declaredOneField(field, orderFiledMap, indexFiledMap, ignoreMap, excelIgnoreUnannotated, convertAllFiled); } - FIELD_CACHE.put(clazz, new SoftReference( + FIELD_CACHE.put(clazz, new SoftReference<>( new FieldCache(buildSortedAllFiledMap(orderFiledMap, indexFiledMap), indexFiledMap, ignoreMap))); } private static Map buildSortedAllFiledMap(Map> orderFiledMap, Map indexFiledMap) { - Map sortedAllFiledMap = new HashMap( + Map sortedAllFiledMap = new HashMap<>( (orderFiledMap.size() + indexFiledMap.size()) * 4 / 3 + 1); - Map tempIndexFiledMap = new HashMap(indexFiledMap); + Map tempIndexFiledMap = new HashMap<>(indexFiledMap); int index = 0; for (List fieldList : orderFiledMap.values()) { for (Field field : fieldList) { @@ -175,11 +176,7 @@ private static void declaredOneField(Field field, Map> orde if (excelProperty != null) { order = excelProperty.order(); } - List orderFiledList = orderFiledMap.get(order); - if (orderFiledList == null) { - orderFiledList = new ArrayList(); - orderFiledMap.put(order, orderFiledList); - } + List orderFiledList = orderFiledMap.computeIfAbsent(order, k -> new ArrayList<>()); orderFiledList.add(field); } diff --git a/ballcat-starters/ballcat-spring-boot-starter-easyexcel/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java b/ballcat-starters/ballcat-spring-boot-starter-easyexcel/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java index 0b499df88..935e296c1 100644 --- a/ballcat-starters/ballcat-spring-boot-starter-easyexcel/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java +++ b/ballcat-starters/ballcat-spring-boot-starter-easyexcel/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java @@ -46,7 +46,7 @@ public void add(List data) { newRowIndex += writeContext.currentWriteHolder().relativeHeadRowIndex(); } // BeanMap is out of order,so use sortedAllFiledMap - Map sortedAllFiledMap = new TreeMap(); + Map sortedAllFiledMap = new TreeMap<>(); int relativeRowIndex = 0; for (Object oneRowData : data) { int n = relativeRowIndex + newRowIndex; @@ -115,7 +115,7 @@ private void addJavaObjectToExcel(Object oneRowData, Row row, int relativeRowInd Map sortedAllFiledMap) { WriteHolder currentWriteHolder = writeContext.currentWriteHolder(); BeanMap beanMap = BeanMap.create(oneRowData); - Set beanMapHandledSet = new HashSet(); + Set beanMapHandledSet = new HashSet<>(); int cellIndex = 0; // If it's a class it needs to be cast by type if (HeadKindEnum.CLASS.equals(writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadKind())) { From dc5c0c474f061540b2facb62a3b419148a1971a7 Mon Sep 17 00:00:00 2001 From: fangyy <596179054@qq.com> Date: Fri, 24 Dec 2021 14:33:11 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=AD=97=E5=85=B8?= =?UTF-8?q?=E9=A1=B9=E6=97=B6=EF=BC=8C=E6=B2=A1=E6=9C=89=E5=B0=86=E5=8F=98?= =?UTF-8?q?=E5=8A=A8=E9=80=9A=E7=9F=A5=E5=88=B0=E5=89=8D=E7=AB=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hccake/ballcat/system/manager/SysDictManager.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ballcat-system/ballcat-system-biz/src/main/java/com/hccake/ballcat/system/manager/SysDictManager.java b/ballcat-system/ballcat-system-biz/src/main/java/com/hccake/ballcat/system/manager/SysDictManager.java index 4d4f30fb8..9f3240d7f 100644 --- a/ballcat-system/ballcat-system-biz/src/main/java/com/hccake/ballcat/system/manager/SysDictManager.java +++ b/ballcat-system/ballcat-system-biz/src/main/java/com/hccake/ballcat/system/manager/SysDictManager.java @@ -175,12 +175,14 @@ public boolean removeDictItemById(Integer id) { throw new BusinessException(BaseResultCode.LOGIC_CHECK_ERROR.getCode(), "该字典项目不能删除"); } // 更新字典项Hash值 - if (sysDictService.updateHashCode(dictCode)) { - return sysDictItemService.removeById(id); - } - else { + if (!sysDictService.updateHashCode(dictCode)) { return false; } + boolean result = sysDictItemService.removeById(id); + if (result) { + eventPublisher.publishEvent(new DictChangeEvent(dictCode)); + } + return true; } /** From 2e77d0d687973fdbc8b8a55f0a9752d77bc28db6 Mon Sep 17 00:00:00 2001 From: huyuanzhi <86774059@qq.com> Date: Sat, 25 Dec 2021 16:35:40 +0800 Subject: [PATCH 6/6] =?UTF-8?q?:art:=E7=A7=9F=E6=88=B7=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ballcat/admin/UpmsAutoConfiguration.java | 50 ++++++++- .../config/mybatis/MybatisPlusConfig.java | 21 ++-- .../admin/config/prop/DbProperties.java | 19 ++++ ballcat-admin/ballcat-admin-tenant/pom.xml | 28 +++++ .../admin/tenant/TenantAutoConfiguration.java | 38 +++++++ .../main/resources/META-INF/spring.factories | 4 + ballcat-admin/pom.xml | 3 +- ballcat-common/ballcat-common-tenant/pom.xml | 46 ++++++++ .../common/tenant/annotation/Tenant.java | 17 +++ .../common/tenant/core/DatasourceType.java | 18 +++ .../common/tenant/core/TenantContext.java | 28 +++++ .../common/tenant/core/TenantDataSource.java | 33 ++++++ .../common/tenant/core/TenantException.java | 16 +++ .../common/tenant/core/TenantType.java | 26 +++++ .../datasource/DataSourceDetailService.java | 27 +++++ .../tenant/plugin/ColumnTenantHandler.java | 35 ++++++ .../tenant/plugin/DataSourceDecoder.java | 50 +++++++++ .../tenant/properties/TenantProperties.java | 46 ++++++++ .../common/tenant/util/CryptoUtils.java | 43 +++++++ ballcat-common/pom.xml | 1 + ballcat-dependencies/pom.xml | 32 +++++- .../pom.xml | 43 +++++++ .../tenant/ColumnTenantInterceptor.java | 93 ++++++++++++++++ .../DynamicDatasourceEnvPostProcessor.java | 59 ++++++++++ .../tenant/TenantAutoConfiguration.java | 68 ++++++++++++ .../tenant/TenantDatasourceLoader.java | 54 +++++++++ .../config/TenantInterceptorConfig.java | 31 ++++++ .../main/resources/META-INF/spring.factories | 7 ++ ballcat-starters/pom.xml | 3 +- ballcat-tenant/ballcat-tenant-biz/pom.xml | 31 ++++++ .../SysDataSourceDetailServiceImpl.java | 57 ++++++++++ .../tenant/mapper/SysDatasourceMapper.java | 35 ++++++ .../mapper/SysTenantDatasourceMapper.java | 35 ++++++ .../tenant/mapper/SysTenantMapper.java | 35 ++++++ .../tenant/service/SysDatasourceService.java | 25 +++++ .../service/SysTenantDatasourceService.java | 25 +++++ .../tenant/service/SysTenantService.java | 25 +++++ .../impl/SysDatasourceServiceImpl.java | 33 ++++++ .../impl/SysTenantDatasourceServiceImpl.java | 33 ++++++ .../service/impl/SysTenantServiceImpl.java | 32 ++++++ .../resources/mapper/SysDatasourceMapper.xml | 46 ++++++++ .../mapper/SysTenantDatasourceMapper.xml | 28 +++++ .../main/resources/mapper/SysTenantMapper.xml | 52 +++++++++ .../ballcat-tenant-controller/pom.xml | 28 +++++ .../controller/SysDatasourceController.java | 89 +++++++++++++++ .../controller/SysTenantController.java | 87 +++++++++++++++ .../SysTenantDatasourceController.java | 89 +++++++++++++++ ballcat-tenant/ballcat-tenant-model/pom.xml | 36 ++++++ .../converter/SysDatasourceConverter.java | 25 +++++ .../tenant/converter/SysTenantConverter.java | 25 +++++ .../SysTenantDatasourceConverter.java | 25 +++++ .../tenant/enums/TenantStatusEnum.java | 28 +++++ .../tenant/model/entity/SysDatasource.java | 93 ++++++++++++++++ .../tenant/model/entity/SysTenant.java | 105 ++++++++++++++++++ .../model/entity/SysTenantDatasource.java | 57 ++++++++++ .../tenant/model/qo/SysDatasourceQO.java | 24 ++++ .../model/qo/SysTenantDatasourceQO.java | 24 ++++ .../ballcat/tenant/model/qo/SysTenantQO.java | 24 ++++ .../tenant/model/vo/SysDatasourcePageVO.java | 85 ++++++++++++++ .../model/vo/SysTenantDatasourcePageVO.java | 49 ++++++++ .../tenant/model/vo/SysTenantPageVO.java | 97 ++++++++++++++++ ballcat-tenant/pom.xml | 24 ++++ doc/update_sql/tenant.sql | 48 ++++++++ pom.xml | 1 + 64 files changed, 2479 insertions(+), 15 deletions(-) create mode 100644 ballcat-admin/ballcat-admin-core/src/main/java/com/hccake/ballcat/admin/config/prop/DbProperties.java create mode 100644 ballcat-admin/ballcat-admin-tenant/pom.xml create mode 100644 ballcat-admin/ballcat-admin-tenant/src/main/java/com/hccake/ballcat/admin/tenant/TenantAutoConfiguration.java create mode 100644 ballcat-admin/ballcat-admin-tenant/src/main/resources/META-INF/spring.factories create mode 100644 ballcat-common/ballcat-common-tenant/pom.xml create mode 100644 ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/annotation/Tenant.java create mode 100644 ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/DatasourceType.java create mode 100644 ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantContext.java create mode 100644 ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantDataSource.java create mode 100644 ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantException.java create mode 100644 ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantType.java create mode 100644 ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/datasource/DataSourceDetailService.java create mode 100644 ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/plugin/ColumnTenantHandler.java create mode 100644 ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/plugin/DataSourceDecoder.java create mode 100644 ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/properties/TenantProperties.java create mode 100644 ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/util/CryptoUtils.java create mode 100644 ballcat-starters/ballcat-spring-boot-starter-tenant/pom.xml create mode 100644 ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/ColumnTenantInterceptor.java create mode 100644 ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/DynamicDatasourceEnvPostProcessor.java create mode 100644 ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/TenantAutoConfiguration.java create mode 100644 ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/TenantDatasourceLoader.java create mode 100644 ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/config/TenantInterceptorConfig.java create mode 100644 ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/resources/META-INF/spring.factories create mode 100644 ballcat-tenant/ballcat-tenant-biz/pom.xml create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/datasource/SysDataSourceDetailServiceImpl.java create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/mapper/SysDatasourceMapper.java create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/mapper/SysTenantDatasourceMapper.java create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/mapper/SysTenantMapper.java create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/SysDatasourceService.java create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/SysTenantDatasourceService.java create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/SysTenantService.java create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/impl/SysDatasourceServiceImpl.java create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/impl/SysTenantDatasourceServiceImpl.java create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/impl/SysTenantServiceImpl.java create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/resources/mapper/SysDatasourceMapper.xml create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/resources/mapper/SysTenantDatasourceMapper.xml create mode 100644 ballcat-tenant/ballcat-tenant-biz/src/main/resources/mapper/SysTenantMapper.xml create mode 100644 ballcat-tenant/ballcat-tenant-controller/pom.xml create mode 100644 ballcat-tenant/ballcat-tenant-controller/src/main/java/com/hccake/ballcat/tenant/controller/SysDatasourceController.java create mode 100644 ballcat-tenant/ballcat-tenant-controller/src/main/java/com/hccake/ballcat/tenant/controller/SysTenantController.java create mode 100644 ballcat-tenant/ballcat-tenant-controller/src/main/java/com/hccake/ballcat/tenant/controller/SysTenantDatasourceController.java create mode 100644 ballcat-tenant/ballcat-tenant-model/pom.xml create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/converter/SysDatasourceConverter.java create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/converter/SysTenantConverter.java create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/converter/SysTenantDatasourceConverter.java create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/enums/TenantStatusEnum.java create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/entity/SysDatasource.java create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/entity/SysTenant.java create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/entity/SysTenantDatasource.java create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/qo/SysDatasourceQO.java create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/qo/SysTenantDatasourceQO.java create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/qo/SysTenantQO.java create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/vo/SysDatasourcePageVO.java create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/vo/SysTenantDatasourcePageVO.java create mode 100644 ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/vo/SysTenantPageVO.java create mode 100644 ballcat-tenant/pom.xml create mode 100644 doc/update_sql/tenant.sql diff --git a/ballcat-admin/ballcat-admin-core/src/main/java/com/hccake/ballcat/admin/UpmsAutoConfiguration.java b/ballcat-admin/ballcat-admin-core/src/main/java/com/hccake/ballcat/admin/UpmsAutoConfiguration.java index 24573371e..964c1690f 100644 --- a/ballcat-admin/ballcat-admin-core/src/main/java/com/hccake/ballcat/admin/UpmsAutoConfiguration.java +++ b/ballcat-admin/ballcat-admin-core/src/main/java/com/hccake/ballcat/admin/UpmsAutoConfiguration.java @@ -1,14 +1,22 @@ package com.hccake.ballcat.admin; +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.core.injector.AbstractMethod; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.hccake.ballcat.admin.config.prop.DbProperties; import com.hccake.ballcat.auth.annotation.EnableOauth2AuthorizationServer; import com.hccake.ballcat.common.security.annotation.EnableOauth2ResourceServer; import com.hccake.ballcat.common.security.properties.SecurityProperties; import com.hccake.ballcat.system.authentication.CustomTokenEnhancer; -import com.hccake.ballcat.system.authentication.SysUserDetailsServiceImpl; import com.hccake.ballcat.system.authentication.DefaultUserInfoCoordinatorImpl; +import com.hccake.ballcat.system.authentication.SysUserDetailsServiceImpl; import com.hccake.ballcat.system.authentication.UserInfoCoordinator; import com.hccake.ballcat.system.properties.UpmsProperties; import com.hccake.ballcat.system.service.SysUserService; +import com.hccake.extend.mybatis.plus.methods.InsertBatchSomeColumnByCollection; +import lombok.AllArgsConstructor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -16,6 +24,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.oauth2.provider.token.TokenEnhancer; @@ -30,7 +40,7 @@ @ComponentScan({ "com.hccake.ballcat.admin", "com.hccake.ballcat.auth", "com.hccake.ballcat.system", "com.hccake.ballcat.log", "com.hccake.ballcat.file", "com.hccake.ballcat.notify" }) @Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties({ UpmsProperties.class, SecurityProperties.class }) +@EnableConfigurationProperties({ UpmsProperties.class, SecurityProperties.class, DbProperties.class }) @EnableOauth2AuthorizationServer @EnableOauth2ResourceServer public class UpmsAutoConfiguration { @@ -78,4 +88,40 @@ public UserInfoCoordinator userInfoCoordinator() { } + @Configuration + @AllArgsConstructor + static class MybatisPlusBeanConfiguration { + + private final DbProperties dbProperties; + + /** + * 分页插件 + * @return InnerInterceptor + */ + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE + 100) + @ConditionalOnMissingBean(PaginationInnerInterceptor.class) + public InnerInterceptor paginationInnerInterceptor() { + PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor(); + // 单页分页条数限制 + paginationInterceptor.setMaxLimit(dbProperties.getMaxLimit()); + // 数据库类型 + paginationInterceptor.setDbType(DbType.MYSQL); + // 生成 countSql 优化掉 join 现在只支持 left join + paginationInterceptor.setOptimizeJoin(dbProperties.isOptimizeJoin()); + return paginationInterceptor; + } + + /** + * 自定义批量插入方法注入 + * @return AbstractMethod + */ + @Bean + public AbstractMethod insertBatchSomeColumnByCollection() { + // 对于只在更新时进行填充的字段不做插入处理 + return new InsertBatchSomeColumnByCollection(t -> t.getFieldFill() != FieldFill.UPDATE); + } + + } + } diff --git a/ballcat-admin/ballcat-admin-core/src/main/java/com/hccake/ballcat/admin/config/mybatis/MybatisPlusConfig.java b/ballcat-admin/ballcat-admin-core/src/main/java/com/hccake/ballcat/admin/config/mybatis/MybatisPlusConfig.java index bc2be6158..e6ce0a5a6 100644 --- a/ballcat-admin/ballcat-admin-core/src/main/java/com/hccake/ballcat/admin/config/mybatis/MybatisPlusConfig.java +++ b/ballcat-admin/ballcat-admin-core/src/main/java/com/hccake/ballcat/admin/config/mybatis/MybatisPlusConfig.java @@ -1,19 +1,17 @@ package com.hccake.ballcat.admin.config.mybatis; -import com.baomidou.mybatisplus.annotation.DbType; -import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.injector.ISqlInjector; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; -import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; import com.hccake.extend.mybatis.plus.injector.CustomSqlInjector; -import com.hccake.extend.mybatis.plus.methods.InsertBatchSomeColumnByCollection; +import lombok.AllArgsConstructor; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.AnnotationAwareOrderComparator; -import java.util.ArrayList; import java.util.List; /** @@ -21,8 +19,13 @@ * @date 2020/04/19 默认配置MybatisPlus分页插件,通过conditional注解达到覆盖效用 */ @Configuration +@AllArgsConstructor public class MybatisPlusConfig { + private final List innerInterceptors; + + private final List injectMethods; + /** * MybatisPlusInterceptor 插件,默认提供分页插件
* 如需其他MP内置插件,则需自定义该Bean @@ -32,7 +35,8 @@ public class MybatisPlusConfig { @ConditionalOnMissingBean(MybatisPlusInterceptor.class) public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); - interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + AnnotationAwareOrderComparator.sort(innerInterceptors); + innerInterceptors.forEach(interceptor::addInnerInterceptor); return interceptor; } @@ -53,10 +57,7 @@ public MetaObjectHandler fillMetaObjectHandle() { @Bean @ConditionalOnMissingBean(ISqlInjector.class) public ISqlInjector customSqlInjector() { - List list = new ArrayList<>(); - // 对于只在更新时进行填充的字段不做插入处理 - list.add(new InsertBatchSomeColumnByCollection(t -> t.getFieldFill() != FieldFill.UPDATE)); - return new CustomSqlInjector(list); + return new CustomSqlInjector(injectMethods); } } diff --git a/ballcat-admin/ballcat-admin-core/src/main/java/com/hccake/ballcat/admin/config/prop/DbProperties.java b/ballcat-admin/ballcat-admin-core/src/main/java/com/hccake/ballcat/admin/config/prop/DbProperties.java new file mode 100644 index 000000000..d153228ab --- /dev/null +++ b/ballcat-admin/ballcat-admin-core/src/main/java/com/hccake/ballcat/admin/config/prop/DbProperties.java @@ -0,0 +1,19 @@ +package com.hccake.ballcat.admin.config.prop; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * 数据库配置属性 + * + * @author huyuanzhi + */ +@Data +@ConfigurationProperties("ballcat.db") +public class DbProperties { + + private Long maxLimit = 500L; + + private boolean optimizeJoin = false; + +} diff --git a/ballcat-admin/ballcat-admin-tenant/pom.xml b/ballcat-admin/ballcat-admin-tenant/pom.xml new file mode 100644 index 000000000..7c1ae609e --- /dev/null +++ b/ballcat-admin/ballcat-admin-tenant/pom.xml @@ -0,0 +1,28 @@ + + + + ballcat-admin + com.hccake + ${revision} + + 4.0.0 + + ballcat-admin-tenant + + + + + + + com.hccake + ballcat-tenant-controller + + + com.hccake + ballcat-spring-boot-starter-tenant + + + + \ No newline at end of file diff --git a/ballcat-admin/ballcat-admin-tenant/src/main/java/com/hccake/ballcat/admin/tenant/TenantAutoConfiguration.java b/ballcat-admin/ballcat-admin-tenant/src/main/java/com/hccake/ballcat/admin/tenant/TenantAutoConfiguration.java new file mode 100644 index 000000000..339ccc321 --- /dev/null +++ b/ballcat-admin/ballcat-admin-tenant/src/main/java/com/hccake/ballcat/admin/tenant/TenantAutoConfiguration.java @@ -0,0 +1,38 @@ +package com.hccake.ballcat.admin.tenant; + +import com.hccake.ballcat.common.tenant.datasource.DataSourceDetailService; +import com.hccake.ballcat.common.tenant.properties.TenantProperties; +import com.hccake.ballcat.tenant.datasource.SysDataSourceDetailServiceImpl; +import com.hccake.ballcat.tenant.service.SysDatasourceService; +import com.hccake.ballcat.tenant.service.SysTenantDatasourceService; +import com.hccake.ballcat.tenant.service.SysTenantService; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + * 租戶注冊 + * + * @author huyuanzhi + */ +@ComponentScan("com.hccake.ballcat.tenant") +public class TenantAutoConfiguration { + + @Configuration(proxyBeanMethods = false) + @ConditionalOnProperty(prefix = TenantProperties.PREFIX, name = "enable", havingValue = "true") + static class DataSourceDetailServiceConfiguration { + + @Bean + @ConditionalOnMissingBean + @ConditionalOnProperty(prefix = TenantProperties.PREFIX, name = "tenantType", havingValue = "DATASOURCE") + public DataSourceDetailService dataSourceDetailService(SysTenantService sysTenantService, + SysDatasourceService sysDatasourceService, SysTenantDatasourceService sysTenantDatasourceService) { + return new SysDataSourceDetailServiceImpl(sysTenantService, sysDatasourceService, + sysTenantDatasourceService); + } + + } + +} diff --git a/ballcat-admin/ballcat-admin-tenant/src/main/resources/META-INF/spring.factories b/ballcat-admin/ballcat-admin-tenant/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..e57e30dfc --- /dev/null +++ b/ballcat-admin/ballcat-admin-tenant/src/main/resources/META-INF/spring.factories @@ -0,0 +1,4 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.hccake.ballcat.admin.tenant.TenantAutoConfiguration + + diff --git a/ballcat-admin/pom.xml b/ballcat-admin/pom.xml index 64c14838b..85b657278 100644 --- a/ballcat-admin/pom.xml +++ b/ballcat-admin/pom.xml @@ -16,6 +16,7 @@ ballcat-admin-core ballcat-admin-websocket ballcat-admin-i18n - + ballcat-admin-tenant + \ No newline at end of file diff --git a/ballcat-common/ballcat-common-tenant/pom.xml b/ballcat-common/ballcat-common-tenant/pom.xml new file mode 100644 index 000000000..a5874858c --- /dev/null +++ b/ballcat-common/ballcat-common-tenant/pom.xml @@ -0,0 +1,46 @@ + + + + ballcat-common + com.hccake + ${revision} + + 4.0.0 + + ballcat-common-tenant + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-autoconfigure + + + com.baomidou + mybatis-plus-core + + + com.baomidou + mybatis-plus-extension + + + org.slf4j + slf4j-api + + + com.baomidou + dynamic-datasource-spring-boot-starter + + + cn.hutool + hutool-crypto + + + + \ No newline at end of file diff --git a/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/annotation/Tenant.java b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/annotation/Tenant.java new file mode 100644 index 000000000..c42c9e809 --- /dev/null +++ b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/annotation/Tenant.java @@ -0,0 +1,17 @@ +package com.hccake.ballcat.common.tenant.annotation; + +import com.baomidou.dynamic.datasource.annotation.DS; + +import java.lang.annotation.*; + +/** + * 切换租户数据源 注意 租户数据源名称一定要是 master + * @author huyuanzhi + */ +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@DS("master") +public @interface Tenant { + +} diff --git a/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/DatasourceType.java b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/DatasourceType.java new file mode 100644 index 000000000..b76dca48a --- /dev/null +++ b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/DatasourceType.java @@ -0,0 +1,18 @@ +package com.hccake.ballcat.common.tenant.core; + +/** + * 数据源连接池类型 + * @author huyuanzhi + */ +public enum DatasourceType { + + /** + * hikari连接池 + */ + HIKARI, + /** + * druid连接池 + */ + DRUID, + +} diff --git a/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantContext.java b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantContext.java new file mode 100644 index 000000000..061f2779f --- /dev/null +++ b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantContext.java @@ -0,0 +1,28 @@ +package com.hccake.ballcat.common.tenant.core; + + +/** + * 保存租户信息 + * + * @author huyuanzhi + */ +public final class TenantContext { + + private static final ThreadLocal THREAD_LOCAL = new InheritableThreadLocal<>(); + + private TenantContext() { + } + + public static void set(String value) { + THREAD_LOCAL.set(value); + } + + public static void clear() { + THREAD_LOCAL.remove(); + } + + public static String get() { + return THREAD_LOCAL.get(); + } + +} diff --git a/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantDataSource.java b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantDataSource.java new file mode 100644 index 000000000..b1dcd7615 --- /dev/null +++ b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantDataSource.java @@ -0,0 +1,33 @@ +package com.hccake.ballcat.common.tenant.core; + +import lombok.Data; + +/** + * 连接池属性 + * + * @author huyuanzhi + */ +@Data +public class TenantDataSource { + + /** + * 连接池名称 + */ + private String poolName; + + /** + * JDBC url 地址 + */ + private String url; + + /** + * JDBC 用户名 + */ + private String username; + + /** + * JDBC 密码 + */ + private String password; + +} diff --git a/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantException.java b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantException.java new file mode 100644 index 000000000..b70e1e613 --- /dev/null +++ b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantException.java @@ -0,0 +1,16 @@ +package com.hccake.ballcat.common.tenant.core; + +/** + * @author huyuanzhi + */ +public class TenantException extends RuntimeException { + + public TenantException(String message) { + super(message); + } + + public TenantException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantType.java b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantType.java new file mode 100644 index 000000000..ceebae581 --- /dev/null +++ b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/core/TenantType.java @@ -0,0 +1,26 @@ +package com.hccake.ballcat.common.tenant.core; + +/** + * @author huyuanzhi + */ + +public enum TenantType { + + /** + * 非租户模式 + */ + NONE, + /** + * 列模式 + */ + COLUMN, + /** + * 单独db模式 + */ + DATASOURCE, + /** + * 混合模式,COLUMN+DATASOURCE + */ + MIX + +} diff --git a/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/datasource/DataSourceDetailService.java b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/datasource/DataSourceDetailService.java new file mode 100644 index 000000000..707f9980a --- /dev/null +++ b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/datasource/DataSourceDetailService.java @@ -0,0 +1,27 @@ +package com.hccake.ballcat.common.tenant.datasource; + +import com.hccake.ballcat.common.tenant.core.TenantDataSource; + +import java.util.List; +import java.util.Map; + +/** + * 获取动态数据源链接属性接口 + * + * @author huyuanzhi + */ +public interface DataSourceDetailService { + + /** + * 获取系统配置的租户数据源链接 + * @return 数据源链接 + */ + List getTenantDataSource(); + + /** + * 获取租户与数据源之间的映射 + * @return 租户数据源映射 + */ + Map getTenantDataSourceMapping(); + +} diff --git a/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/plugin/ColumnTenantHandler.java b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/plugin/ColumnTenantHandler.java new file mode 100644 index 000000000..43f924341 --- /dev/null +++ b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/plugin/ColumnTenantHandler.java @@ -0,0 +1,35 @@ +package com.hccake.ballcat.common.tenant.plugin; + +import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; +import com.hccake.ballcat.common.tenant.core.TenantContext; +import com.hccake.ballcat.common.tenant.properties.TenantProperties; +import lombok.AllArgsConstructor; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.StringValue; + +/** + * column 模式租户处理 + * + * @author huyuanzhi + */ +@AllArgsConstructor +public class ColumnTenantHandler implements TenantLineHandler { + + private final TenantProperties tenantProperties; + + @Override + public Expression getTenantId() { + return new StringValue(TenantContext.get()); + } + + @Override + public String getTenantIdColumn() { + return tenantProperties.getTenantColumn(); + } + + @Override + public boolean ignoreTable(String tableName) { + return tenantProperties.getIgnoreTables().stream().anyMatch(tableName::equalsIgnoreCase); + } + +} diff --git a/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/plugin/DataSourceDecoder.java b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/plugin/DataSourceDecoder.java new file mode 100644 index 000000000..ad6a4fd5c --- /dev/null +++ b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/plugin/DataSourceDecoder.java @@ -0,0 +1,50 @@ +package com.hccake.ballcat.common.tenant.plugin; + +import com.baomidou.dynamic.datasource.event.DataSourceInitEvent; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; +import com.baomidou.dynamic.datasource.toolkit.CryptoUtils; +import com.hccake.ballcat.common.tenant.properties.TenantProperties; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.StringUtils; + +import javax.sql.DataSource; + +/** + * 动态数据源解密 + * + * @author huyuanzhi + */ +@Slf4j +@AllArgsConstructor +public class DataSourceDecoder implements DataSourceInitEvent { + + private final TenantProperties tenantProperties; + + @Override + public void beforeCreate(DataSourceProperty dataSourceProperty) { + String secretKey = tenantProperties.getSecretKey(); + if (StringUtils.hasText(secretKey)) { + dataSourceProperty.setUrl(this.decrypt(secretKey, dataSourceProperty.getUrl())); + dataSourceProperty.setUsername(this.decrypt(secretKey, dataSourceProperty.getUsername())); + dataSourceProperty.setPassword(this.decrypt(secretKey, dataSourceProperty.getPassword())); + } + } + + private String decrypt(String secretKey, String cipherText) { + if (StringUtils.hasText(cipherText)) { + try { + return CryptoUtils.decrypt(secretKey, cipherText); + } + catch (Exception var5) { + log.error("DynamicDataSourceProperties.decrypt error ", var5); + } + } + return cipherText; + } + + @Override + public void afterCreate(DataSource dataSource) { + } + +} diff --git a/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/properties/TenantProperties.java b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/properties/TenantProperties.java new file mode 100644 index 000000000..10e9f432e --- /dev/null +++ b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/properties/TenantProperties.java @@ -0,0 +1,46 @@ +package com.hccake.ballcat.common.tenant.properties; + +import com.hccake.ballcat.common.tenant.core.DatasourceType; +import com.hccake.ballcat.common.tenant.core.TenantType; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; + +import java.util.ArrayList; +import java.util.List; + +/** + * 租户配置 + * + * @author huyuanzhi + */ +@Data +@ConfigurationProperties(TenantProperties.PREFIX) +public class TenantProperties { + + public static final String PREFIX = "ballcat.db.tenant"; + + private static final PathMatcher ANT_PATH_MATCHER = new AntPathMatcher(); + + private boolean enable = false; + + private TenantType tenantType = TenantType.NONE; + + private String tenantColumn = "tenant_code"; + + private List ignoreTables = new ArrayList<>(); + + private String headerTenantKey = "tenant"; + + private List ignorePath = new ArrayList<>(); + + private DatasourceType datasourceType = DatasourceType.HIKARI; + + private String secretKey = "ballcat"; + + public boolean isIgnoreTenantUri(String path) { + return ignorePath.stream().anyMatch(url -> path.startsWith(url) || ANT_PATH_MATCHER.match(url, path)); + } + +} diff --git a/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/util/CryptoUtils.java b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/util/CryptoUtils.java new file mode 100644 index 000000000..6c2169763 --- /dev/null +++ b/ballcat-common/ballcat-common-tenant/src/main/java/com/hccake/ballcat/common/tenant/util/CryptoUtils.java @@ -0,0 +1,43 @@ +package com.hccake.ballcat.common.tenant.util; + +import cn.hutool.core.codec.Base64; +import cn.hutool.crypto.Mode; +import cn.hutool.crypto.Padding; +import cn.hutool.crypto.symmetric.AES; + +import java.nio.charset.StandardCharsets; + +/** + * @author huyuanzhi + */ +public final class CryptoUtils { + + private CryptoUtils() { + } + + /** + * 将密文解密为明文 + * @param aesPass AES加密后的密文 + * @param secretKey 密钥 + * @return 明文密码 + */ + public static String decodeAes(String aesPass, String secretKey) { + byte[] secretKeyBytes = secretKey.getBytes(); + AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, secretKeyBytes, secretKeyBytes); + byte[] result = aes.decrypt(Base64.decode(aesPass.getBytes(StandardCharsets.UTF_8))); + return new String(result, StandardCharsets.UTF_8); + } + + /** + * 将明文密码加密为密文 + * @param password 明文密码 + * @param secretKey 密钥 + * @return AES加密后的密文 + */ + public static String encodeAes(String password, String secretKey) { + byte[] secretKeyBytes = secretKey.getBytes(); + AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, secretKeyBytes, secretKeyBytes); + return aes.encryptBase64(password, StandardCharsets.UTF_8); + } + +} diff --git a/ballcat-common/pom.xml b/ballcat-common/pom.xml index 9f94cde74..7a73d5f6a 100644 --- a/ballcat-common/pom.xml +++ b/ballcat-common/pom.xml @@ -23,6 +23,7 @@ ballcat-common-log ballcat-common-redis ballcat-common-i18n + ballcat-common-tenant diff --git a/ballcat-dependencies/pom.xml b/ballcat-dependencies/pom.xml index 66bc61d00..90c693b05 100644 --- a/ballcat-dependencies/pom.xml +++ b/ballcat-dependencies/pom.xml @@ -110,6 +110,11 @@ ballcat-admin-core ${revision} + + com.hccake + ballcat-admin-tenant + ${revision} + com.hccake ballcat-admin-websocket @@ -155,6 +160,11 @@ ballcat-common-security ${revision} + + com.hccake + ballcat-common-tenant + ${revision} + com.hccake ballcat-common-util @@ -251,6 +261,11 @@ ballcat-spring-boot-starter-xss ${revision} + + com.hccake + ballcat-spring-boot-starter-tenant + ${revision} + com.hccake ballcat-admin-i18n @@ -313,6 +328,22 @@ ballcat-system-model ${revision} + + + com.hccake + ballcat-tenant-controller + ${revision} + + + com.hccake + ballcat-tenant-biz + ${revision} + + + com.hccake + ballcat-tenant-model + ${revision} + com.hccake @@ -633,7 +664,6 @@ commons-net 3.8.0 - com.nimbusds oauth2-oidc-sdk diff --git a/ballcat-starters/ballcat-spring-boot-starter-tenant/pom.xml b/ballcat-starters/ballcat-spring-boot-starter-tenant/pom.xml new file mode 100644 index 000000000..61d87d3f4 --- /dev/null +++ b/ballcat-starters/ballcat-spring-boot-starter-tenant/pom.xml @@ -0,0 +1,43 @@ + + + + ballcat-starters + com.hccake + ${revision} + + 4.0.0 + + ballcat-spring-boot-starter-tenant + + + + + + + + com.hccake + ballcat-common-tenant + + + org.springframework + spring-webmvc + true + + + javax.servlet + javax.servlet-api + true + + + com.hccake + ballcat-common-model + + + com.hccake + ballcat-common-util + + + + \ No newline at end of file diff --git a/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/ColumnTenantInterceptor.java b/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/ColumnTenantInterceptor.java new file mode 100644 index 000000000..aff61433b --- /dev/null +++ b/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/ColumnTenantInterceptor.java @@ -0,0 +1,93 @@ +package com.hccake.ballcat.autoconfigure.tenant; + +import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder; +import com.hccake.ballcat.common.model.result.R; +import com.hccake.ballcat.common.model.result.SystemResultCode; +import com.hccake.ballcat.common.tenant.core.TenantContext; +import com.hccake.ballcat.common.tenant.core.TenantException; +import com.hccake.ballcat.common.tenant.core.TenantType; +import com.hccake.ballcat.common.tenant.datasource.DataSourceDetailService; +import com.hccake.ballcat.common.tenant.properties.TenantProperties; +import com.hccake.ballcat.common.util.JsonUtils; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.util.StringUtils; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +/** + * 租户模式下解析租户代码,并存入上下文 + * + * @author huyuanzhi + */ +@Slf4j +@AllArgsConstructor +public class ColumnTenantInterceptor implements HandlerInterceptor { + + private final TenantProperties tenantProperties; + + private final DataSourceDetailService dataSourceDetailService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws IOException { + try { + parseTenant(request); + return true; + } + catch (TenantException e) { + response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON.toString()); + response.setHeader(HttpHeaders.ACCEPT_CHARSET, StandardCharsets.UTF_8.toString()); + response.setStatus(HttpStatus.BAD_REQUEST.value()); + R result = R.failed(SystemResultCode.UNAUTHORIZED, e.getMessage()); + response.getWriter().write(JsonUtils.toJson(result)); + } + return false; + } + + private void parseTenant(HttpServletRequest request) { + if (isIgnoreTenant(request.getRequestURI())) { + return; + } + String tenantCode = request.getHeader(tenantProperties.getHeaderTenantKey()); + if (!StringUtils.hasText(tenantCode)) { + log.error("获取租户代码为空,uri:{}", request.getRequestURI()); + throw new TenantException("获取租户代码为空!"); + } + TenantContext.set(tenantCode); + // 如果是数据源模式,则需要切换数据源 + // TODO 暫時只有兩種模式,後期模式多了再抽象 + if (tenantProperties.getTenantType() == TenantType.DATASOURCE) { + doDetermineDatasource(tenantCode); + } + } + + private void doDetermineDatasource(String tenantCode) { + Map mapping = dataSourceDetailService.getTenantDataSourceMapping(); + String dataSourceKey = mapping.get(tenantCode); + if (!StringUtils.hasLength(dataSourceKey)) { + log.error("获取数据源失败,租户代码:{},数据源映射:{}", tenantCode, mapping); + throw new TenantException("获取租户数据源失败!"); + } + DynamicDataSourceContextHolder.push(dataSourceKey); + } + + private boolean isIgnoreTenant(String path) { + return tenantProperties.isIgnoreTenantUri(path); + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, + Exception ex) { + TenantContext.clear(); + } + +} diff --git a/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/DynamicDatasourceEnvPostProcessor.java b/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/DynamicDatasourceEnvPostProcessor.java new file mode 100644 index 000000000..7dad5391c --- /dev/null +++ b/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/DynamicDatasourceEnvPostProcessor.java @@ -0,0 +1,59 @@ +package com.hccake.ballcat.autoconfigure.tenant; + +import cn.hutool.core.text.StrPool; +import com.hccake.ballcat.common.tenant.core.TenantType; +import com.hccake.ballcat.common.tenant.properties.TenantProperties; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; + +import java.util.HashMap; +import java.util.Map; + +/** + * 非数据源模式时动态数据源不加载 + * + * @author soundhu + */ +@ConditionalOnProperty(prefix = TenantProperties.PREFIX, name = "enable", havingValue = "true") +public class DynamicDatasourceEnvPostProcessor implements EnvironmentPostProcessor { + + public static final String DYNAMIC_DATASOURCE_ENABLE = "spring.datasource.dynamic.enabled"; + + public static final String TENANT_TYPE = "ballcat.db.tenant.tenantType"; + + private static final String REPLACE_SOURCE_NAME = "replaceEnvironment"; + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + String tenantType = environment.getProperty(TENANT_TYPE); + if (TenantType.DATASOURCE.name().equals(tenantType)) { + return; + } + Map map = new HashMap<>(1); + map.put(DYNAMIC_DATASOURCE_ENABLE, Boolean.FALSE.toString()); + replaceProperties(environment.getPropertySources(), map); + } + + private void replaceProperties(MutablePropertySources propertySources, Map map) { + MapPropertySource target = null; + if (propertySources.contains(REPLACE_SOURCE_NAME)) { + PropertySource source = propertySources.get(REPLACE_SOURCE_NAME); + if (source instanceof MapPropertySource) { + target = (MapPropertySource) source; + target.getSource().putAll(map); + } + } + if (target == null) { + target = new MapPropertySource(REPLACE_SOURCE_NAME, map); + } + if (!propertySources.contains(REPLACE_SOURCE_NAME)) { + propertySources.addFirst(target); + } + } + +} diff --git a/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/TenantAutoConfiguration.java b/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/TenantAutoConfiguration.java new file mode 100644 index 000000000..27000b39c --- /dev/null +++ b/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/TenantAutoConfiguration.java @@ -0,0 +1,68 @@ +package com.hccake.ballcat.autoconfigure.tenant; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.dynamic.datasource.event.DataSourceInitEvent; +import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider; +import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; +import com.baomidou.dynamic.datasource.support.DdConstants; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; +import com.hccake.ballcat.common.tenant.datasource.DataSourceDetailService; +import com.hccake.ballcat.common.tenant.plugin.ColumnTenantHandler; +import com.hccake.ballcat.common.tenant.plugin.DataSourceDecoder; +import com.hccake.ballcat.common.tenant.properties.TenantProperties; +import lombok.AllArgsConstructor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; + +import javax.sql.DataSource; +import java.util.HashMap; +import java.util.Map; + +/** + * 租户自动配置类 + * + * @author huyuanzhi + */ +@AllArgsConstructor +@EnableConfigurationProperties({ TenantProperties.class }) +@ConditionalOnProperty(prefix = TenantProperties.PREFIX, name = "enable", havingValue = "true") +public class TenantAutoConfiguration { + + private final TenantProperties tenantProperties; + + @Bean + @ConditionalOnMissingBean(TenantLineInnerInterceptor.class) + @ConditionalOnProperty(prefix = TenantProperties.PREFIX, name = "tenantType", havingValue = "COLUMN") + public InnerInterceptor columnTenantInterceptor() { + return new TenantLineInnerInterceptor(new ColumnTenantHandler(tenantProperties)); + } + + @Bean + @ConditionalOnBean(DataSourceDetailService.class) + @ConditionalOnMissingBean(DataSourceInitEvent.class) + public DataSourceInitEvent dataSourceInitEvent() { + return new DataSourceDecoder(tenantProperties); + } + + @ConditionalOnProperty(prefix = TenantProperties.PREFIX, name = "tenantType", havingValue = "DATASOURCE") + public DynamicDataSourceProvider masterDataSource(DataSourceProperties dataSourceProperties) { + return new AbstractDataSourceProvider() { + @Override + public Map loadDataSources() { + // 添加主数据源 + Map dataSourcePropertiesMap = new HashMap<>(8); + DataSourceProperty masterDataSourceProperty = new DataSourceProperty(); + BeanUtil.copyProperties(dataSourceProperties, masterDataSourceProperty); + dataSourcePropertiesMap.put(DdConstants.MASTER, masterDataSourceProperty); + return createDataSourceMap(dataSourcePropertiesMap); + } + }; + } + +} diff --git a/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/TenantDatasourceLoader.java b/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/TenantDatasourceLoader.java new file mode 100644 index 000000000..e5c09f688 --- /dev/null +++ b/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/TenantDatasourceLoader.java @@ -0,0 +1,54 @@ +package com.hccake.ballcat.autoconfigure.tenant; + +import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; +import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; +import com.hccake.ballcat.common.tenant.core.DatasourceType; +import com.hccake.ballcat.common.tenant.datasource.DataSourceDetailService; +import com.hccake.ballcat.common.tenant.core.TenantDataSource; +import com.hccake.ballcat.common.tenant.properties.TenantProperties; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +/** + * 动态加载租户数据源 + * + * @author huyuanzhi + */ +@Slf4j +@Configuration +@AllArgsConstructor +@ConditionalOnBean(DataSourceDetailService.class) +@ConditionalOnProperty(prefix = TenantProperties.PREFIX, name = {"tenantType"}, havingValue = "DATASOURCE") +public class TenantDatasourceLoader implements CommandLineRunner { + + private final DataSourceDetailService dataSourceDetailService; + + private final TenantProperties tenantProperties; + + private final DataSource dataSource; + + private final DefaultDataSourceCreator dataSourceCreator; + + @Override + public void run(String... args) throws Exception { + DatasourceType datasourceType = tenantProperties.getDatasourceType(); + log.info("系统初始化完成,开始加载租户数据源,数据源类型:{}", datasourceType.name()); + for (TenantDataSource tenantDataSource : dataSourceDetailService.getTenantDataSource()) { + DataSourceProperty dataSourceProperty = new DataSourceProperty(); + BeanUtils.copyProperties(tenantDataSource, dataSourceProperty); + DynamicRoutingDataSource routingDataSource = (DynamicRoutingDataSource) dataSource; + DataSource ds = dataSourceCreator.createDataSource(dataSourceProperty); + routingDataSource.addDataSource(tenantDataSource.getPoolName(), ds); + log.info("数据源:{}初始化完成!", tenantDataSource.getPoolName()); + } + } + +} diff --git a/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/config/TenantInterceptorConfig.java b/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/config/TenantInterceptorConfig.java new file mode 100644 index 000000000..958951a9a --- /dev/null +++ b/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/java/com/hccake/ballcat/autoconfigure/tenant/config/TenantInterceptorConfig.java @@ -0,0 +1,31 @@ +package com.hccake.ballcat.autoconfigure.tenant.config; + +import com.hccake.ballcat.autoconfigure.tenant.ColumnTenantInterceptor; +import com.hccake.ballcat.common.tenant.datasource.DataSourceDetailService; +import com.hccake.ballcat.common.tenant.properties.TenantProperties; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * @author huyuanzhi + */ +@Slf4j +public class TenantInterceptorConfig implements WebMvcConfigurer { + + @Autowired + private TenantProperties tenantProperties; + + @Autowired(required = false) + private DataSourceDetailService dataSourceDetailService; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + if (tenantProperties.isEnable()) { + registry.addInterceptor(new ColumnTenantInterceptor(tenantProperties, dataSourceDetailService)); + log.debug("租户模式已开启,注册租户拦截器完成!"); + } + } + +} diff --git a/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/resources/META-INF/spring.factories b/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..6694ba08d --- /dev/null +++ b/ballcat-starters/ballcat-spring-boot-starter-tenant/src/main/resources/META-INF/spring.factories @@ -0,0 +1,7 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.hccake.ballcat.autoconfigure.tenant.TenantAutoConfiguration,\ + com.hccake.ballcat.autoconfigure.tenant.TenantDatasourceLoader,\ + com.hccake.ballcat.autoconfigure.tenant.config.TenantInterceptorConfig + +org.springframework.boot.env.EnvironmentPostProcessor=\ + com.hccake.ballcat.autoconfigure.tenant.DynamicDatasourceEnvPostProcessor \ No newline at end of file diff --git a/ballcat-starters/pom.xml b/ballcat-starters/pom.xml index f8a235fd6..8dff54c34 100644 --- a/ballcat-starters/pom.xml +++ b/ballcat-starters/pom.xml @@ -30,6 +30,7 @@ ballcat-spring-boot-starter-xss ballcat-spring-boot-starter-i18n ballcat-spring-boot-starter-file - + ballcat-spring-boot-starter-tenant + \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-biz/pom.xml b/ballcat-tenant/ballcat-tenant-biz/pom.xml new file mode 100644 index 000000000..aaad19f19 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/pom.xml @@ -0,0 +1,31 @@ + + + + ballcat-tenant + com.hccake + ${revision} + + 4.0.0 + ballcat-tenant-biz + + + + + + + com.hccake + ballcat-tenant-model + + + com.hccake + ballcat-common-security + + + com.hccake + ballcat-common-tenant + + + + \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/datasource/SysDataSourceDetailServiceImpl.java b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/datasource/SysDataSourceDetailServiceImpl.java new file mode 100644 index 000000000..071f25035 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/datasource/SysDataSourceDetailServiceImpl.java @@ -0,0 +1,57 @@ +package com.hccake.ballcat.tenant.datasource; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.text.CharSequenceUtil; +import com.hccake.ballcat.common.tenant.core.TenantDataSource; +import com.hccake.ballcat.common.tenant.datasource.DataSourceDetailService; +import com.hccake.ballcat.tenant.model.entity.SysDatasource; +import com.hccake.ballcat.tenant.model.entity.SysTenant; +import com.hccake.ballcat.tenant.service.SysDatasourceService; +import com.hccake.ballcat.tenant.service.SysTenantDatasourceService; +import com.hccake.ballcat.tenant.service.SysTenantService; +import lombok.AllArgsConstructor; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author huyuanzhi + */ +@AllArgsConstructor +public class SysDataSourceDetailServiceImpl implements DataSourceDetailService { + + private final SysTenantService sysTenantService; + + private final SysDatasourceService sysDatasourceService; + + private final SysTenantDatasourceService sysTenantDatasourceService; + + @Override + public List getTenantDataSource() { + return sysDatasourceService.list().stream().map(d -> { + TenantDataSource tenantDataSource = BeanUtil.toBean(d, TenantDataSource.class); + tenantDataSource.setPoolName(d.getName()); + return tenantDataSource; + }).collect(Collectors.toList()); + } + + @Override + public Map getTenantDataSourceMapping() { + Map dataSourceMap = sysDatasourceService.list().stream() + .collect(Collectors.toMap(SysDatasource::getId, SysDatasource::getName)); + Map tenantMap = sysTenantService.list().stream() + .collect(Collectors.toMap(SysTenant::getTenantId, SysTenant::getTenantCode)); + Map mapping = new HashMap<>(tenantMap.size()); + sysTenantDatasourceService.list().forEach(std -> { + String tenantCode = tenantMap.get(std.getTenantId()); + String dataSource = dataSourceMap.get(std.getDatasourceId()); + if (CharSequenceUtil.isAllNotEmpty(tenantCode, dataSource)) { + mapping.put(tenantCode, dataSource); + } + }); + return mapping; + } + +} diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/mapper/SysDatasourceMapper.java b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/mapper/SysDatasourceMapper.java new file mode 100644 index 000000000..ae04cb936 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/mapper/SysDatasourceMapper.java @@ -0,0 +1,35 @@ +package com.hccake.ballcat.tenant.mapper; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.hccake.ballcat.tenant.converter.SysDatasourceConverter; +import com.hccake.ballcat.tenant.model.entity.SysDatasource; +import com.hccake.ballcat.tenant.model.qo.SysDatasourceQO; +import com.hccake.ballcat.tenant.model.vo.SysDatasourcePageVO; +import com.hccake.ballcat.common.model.domain.PageParam; +import com.hccake.ballcat.common.model.domain.PageResult; +import com.hccake.extend.mybatis.plus.conditions.query.LambdaQueryWrapperX; +import com.hccake.extend.mybatis.plus.mapper.ExtendMapper; +import com.hccake.extend.mybatis.plus.toolkit.WrappersX; + +/** + * 数据源表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +public interface SysDatasourceMapper extends ExtendMapper { + + /** + * 分页查询 + * @param pageParam 分页参数 + * @param qo 查询参数 + * @return PageResult VO分页数据 + */ + default PageResult queryPage(PageParam pageParam, SysDatasourceQO qo) { + IPage page = this.prodPage(pageParam); + LambdaQueryWrapperX wrapper = WrappersX.lambdaQueryX(SysDatasource.class); + this.selectPage(page, wrapper); + IPage voPage = page.convert(SysDatasourceConverter.INSTANCE::poToPageVo); + return new PageResult<>(voPage.getRecords(), voPage.getTotal()); + } + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/mapper/SysTenantDatasourceMapper.java b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/mapper/SysTenantDatasourceMapper.java new file mode 100644 index 000000000..47448f756 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/mapper/SysTenantDatasourceMapper.java @@ -0,0 +1,35 @@ +package com.hccake.ballcat.tenant.mapper; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.hccake.ballcat.tenant.converter.SysTenantDatasourceConverter; +import com.hccake.ballcat.tenant.model.entity.SysTenantDatasource; +import com.hccake.ballcat.tenant.model.qo.SysTenantDatasourceQO; +import com.hccake.ballcat.tenant.model.vo.SysTenantDatasourcePageVO; +import com.hccake.ballcat.common.model.domain.PageParam; +import com.hccake.ballcat.common.model.domain.PageResult; +import com.hccake.extend.mybatis.plus.conditions.query.LambdaQueryWrapperX; +import com.hccake.extend.mybatis.plus.mapper.ExtendMapper; +import com.hccake.extend.mybatis.plus.toolkit.WrappersX; + +/** + * 租户数据源映射表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +public interface SysTenantDatasourceMapper extends ExtendMapper { + + /** + * 分页查询 + * @param pageParam 分页参数 + * @param qo 查询参数 + * @return PageResult VO分页数据 + */ + default PageResult queryPage(PageParam pageParam, SysTenantDatasourceQO qo) { + IPage page = this.prodPage(pageParam); + LambdaQueryWrapperX wrapper = WrappersX.lambdaQueryX(SysTenantDatasource.class); + this.selectPage(page, wrapper); + IPage voPage = page.convert(SysTenantDatasourceConverter.INSTANCE::poToPageVo); + return new PageResult<>(voPage.getRecords(), voPage.getTotal()); + } + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/mapper/SysTenantMapper.java b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/mapper/SysTenantMapper.java new file mode 100644 index 000000000..5539dd93f --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/mapper/SysTenantMapper.java @@ -0,0 +1,35 @@ +package com.hccake.ballcat.tenant.mapper; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.hccake.ballcat.tenant.converter.SysTenantConverter; +import com.hccake.ballcat.tenant.model.entity.SysTenant; +import com.hccake.ballcat.tenant.model.qo.SysTenantQO; +import com.hccake.ballcat.tenant.model.vo.SysTenantPageVO; +import com.hccake.ballcat.common.model.domain.PageParam; +import com.hccake.ballcat.common.model.domain.PageResult; +import com.hccake.extend.mybatis.plus.conditions.query.LambdaQueryWrapperX; +import com.hccake.extend.mybatis.plus.mapper.ExtendMapper; +import com.hccake.extend.mybatis.plus.toolkit.WrappersX; + +/** + * 租户表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +public interface SysTenantMapper extends ExtendMapper { + + /** + * 分页查询 + * @param pageParam 分页参数 + * @param qo 查询参数 + * @return PageResult VO分页数据 + */ + default PageResult queryPage(PageParam pageParam, SysTenantQO qo) { + IPage page = this.prodPage(pageParam); + LambdaQueryWrapperX wrapper = WrappersX.lambdaQueryX(SysTenant.class); + this.selectPage(page, wrapper); + IPage voPage = page.convert(SysTenantConverter.INSTANCE::poToPageVo); + return new PageResult<>(voPage.getRecords(), voPage.getTotal()); + } + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/SysDatasourceService.java b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/SysDatasourceService.java new file mode 100644 index 000000000..b3f0bd8f1 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/SysDatasourceService.java @@ -0,0 +1,25 @@ +package com.hccake.ballcat.tenant.service; + +import com.hccake.ballcat.common.model.domain.PageParam; +import com.hccake.ballcat.common.model.domain.PageResult; +import com.hccake.ballcat.tenant.model.entity.SysDatasource; +import com.hccake.ballcat.tenant.model.qo.SysDatasourceQO; +import com.hccake.ballcat.tenant.model.vo.SysDatasourcePageVO; +import com.hccake.extend.mybatis.plus.service.ExtendService; + +/** + * 数据源表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +public interface SysDatasourceService extends ExtendService { + + /** + * 根据QueryObeject查询分页数据 + * @param pageParam 分页参数 + * @param qo 查询参数对象 + * @return PageResult<SysDatasourcePageVO> 分页数据 + */ + PageResult queryPage(PageParam pageParam, SysDatasourceQO qo); + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/SysTenantDatasourceService.java b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/SysTenantDatasourceService.java new file mode 100644 index 000000000..e1bfb90c9 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/SysTenantDatasourceService.java @@ -0,0 +1,25 @@ +package com.hccake.ballcat.tenant.service; + +import com.hccake.ballcat.tenant.model.entity.SysTenantDatasource; +import com.hccake.ballcat.tenant.model.vo.SysTenantDatasourcePageVO; +import com.hccake.ballcat.tenant.model.qo.SysTenantDatasourceQO; +import com.hccake.ballcat.common.model.domain.PageParam; +import com.hccake.ballcat.common.model.domain.PageResult; +import com.hccake.extend.mybatis.plus.service.ExtendService; + +/** + * 租户数据源映射表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +public interface SysTenantDatasourceService extends ExtendService { + + /** + * 根据QueryObeject查询分页数据 + * @param pageParam 分页参数 + * @param qo 查询参数对象 + * @return PageResult<SysTenantDatasourcePageVO> 分页数据 + */ + PageResult queryPage(PageParam pageParam, SysTenantDatasourceQO qo); + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/SysTenantService.java b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/SysTenantService.java new file mode 100644 index 000000000..3d9e23554 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/SysTenantService.java @@ -0,0 +1,25 @@ +package com.hccake.ballcat.tenant.service; + +import com.hccake.ballcat.tenant.model.entity.SysTenant; +import com.hccake.ballcat.tenant.model.vo.SysTenantPageVO; +import com.hccake.ballcat.tenant.model.qo.SysTenantQO; +import com.hccake.ballcat.common.model.domain.PageParam; +import com.hccake.ballcat.common.model.domain.PageResult; +import com.hccake.extend.mybatis.plus.service.ExtendService; + +/** + * 租户表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +public interface SysTenantService extends ExtendService { + + /** + * 根据QueryObeject查询分页数据 + * @param pageParam 分页参数 + * @param qo 查询参数对象 + * @return PageResult<SysTenantPageVO> 分页数据 + */ + PageResult queryPage(PageParam pageParam, SysTenantQO qo); + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/impl/SysDatasourceServiceImpl.java b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/impl/SysDatasourceServiceImpl.java new file mode 100644 index 000000000..d30c579a1 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/impl/SysDatasourceServiceImpl.java @@ -0,0 +1,33 @@ +package com.hccake.ballcat.tenant.service.impl; + +import com.hccake.ballcat.common.model.domain.PageParam; +import com.hccake.ballcat.common.model.domain.PageResult; +import com.hccake.ballcat.tenant.mapper.SysDatasourceMapper; +import com.hccake.ballcat.tenant.model.entity.SysDatasource; +import com.hccake.ballcat.tenant.model.qo.SysDatasourceQO; +import com.hccake.ballcat.tenant.model.vo.SysDatasourcePageVO; +import com.hccake.ballcat.tenant.service.SysDatasourceService; +import com.hccake.extend.mybatis.plus.service.impl.ExtendServiceImpl; +import org.springframework.stereotype.Service; + +/** + * 数据源表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Service +public class SysDatasourceServiceImpl extends ExtendServiceImpl + implements SysDatasourceService { + + /** + * 根据QueryObeject查询分页数据 + * @param pageParam 分页参数 + * @param qo 查询参数对象 + * @return PageResult 分页数据 + */ + @Override + public PageResult queryPage(PageParam pageParam, SysDatasourceQO qo) { + return baseMapper.queryPage(pageParam, qo); + } + +} diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/impl/SysTenantDatasourceServiceImpl.java b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/impl/SysTenantDatasourceServiceImpl.java new file mode 100644 index 000000000..635619cae --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/impl/SysTenantDatasourceServiceImpl.java @@ -0,0 +1,33 @@ +package com.hccake.ballcat.tenant.service.impl; + +import com.hccake.ballcat.tenant.model.entity.SysTenantDatasource; +import com.hccake.ballcat.tenant.model.vo.SysTenantDatasourcePageVO; +import com.hccake.ballcat.tenant.model.qo.SysTenantDatasourceQO; +import com.hccake.ballcat.tenant.mapper.SysTenantDatasourceMapper; +import com.hccake.ballcat.tenant.service.SysTenantDatasourceService; +import com.hccake.ballcat.common.model.domain.PageParam; +import com.hccake.ballcat.common.model.domain.PageResult; +import com.hccake.extend.mybatis.plus.service.impl.ExtendServiceImpl; +import org.springframework.stereotype.Service; + +/** + * 租户数据源映射表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Service +public class SysTenantDatasourceServiceImpl extends ExtendServiceImpl + implements SysTenantDatasourceService { + + /** + * 根据QueryObeject查询分页数据 + * @param pageParam 分页参数 + * @param qo 查询参数对象 + * @return PageResult 分页数据 + */ + @Override + public PageResult queryPage(PageParam pageParam, SysTenantDatasourceQO qo) { + return baseMapper.queryPage(pageParam, qo); + } + +} diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/impl/SysTenantServiceImpl.java b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/impl/SysTenantServiceImpl.java new file mode 100644 index 000000000..88c914601 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/java/com/hccake/ballcat/tenant/service/impl/SysTenantServiceImpl.java @@ -0,0 +1,32 @@ +package com.hccake.ballcat.tenant.service.impl; + +import com.hccake.ballcat.tenant.model.entity.SysTenant; +import com.hccake.ballcat.tenant.model.vo.SysTenantPageVO; +import com.hccake.ballcat.tenant.model.qo.SysTenantQO; +import com.hccake.ballcat.tenant.mapper.SysTenantMapper; +import com.hccake.ballcat.tenant.service.SysTenantService; +import com.hccake.ballcat.common.model.domain.PageParam; +import com.hccake.ballcat.common.model.domain.PageResult; +import com.hccake.extend.mybatis.plus.service.impl.ExtendServiceImpl; +import org.springframework.stereotype.Service; + +/** + * 租户表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Service +public class SysTenantServiceImpl extends ExtendServiceImpl implements SysTenantService { + + /** + * 根据QueryObeject查询分页数据 + * @param pageParam 分页参数 + * @param qo 查询参数对象 + * @return PageResult 分页数据 + */ + @Override + public PageResult queryPage(PageParam pageParam, SysTenantQO qo) { + return baseMapper.queryPage(pageParam, qo); + } + +} diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/resources/mapper/SysDatasourceMapper.xml b/ballcat-tenant/ballcat-tenant-biz/src/main/resources/mapper/SysDatasourceMapper.xml new file mode 100644 index 000000000..d86840703 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/resources/mapper/SysDatasourceMapper.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + id, + name, + url, + username, + password, + type, + max_holds, + extra, + description, + create_time, + update_time + + + + sd.id, + sd.name, + sd.url, + sd.username, + sd.password, + sd.type, + sd.max_holds, + sd.extra, + sd.description, + sd.create_time, + sd.update_time + + \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/resources/mapper/SysTenantDatasourceMapper.xml b/ballcat-tenant/ballcat-tenant-biz/src/main/resources/mapper/SysTenantDatasourceMapper.xml new file mode 100644 index 000000000..9a2257b21 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/resources/mapper/SysTenantDatasourceMapper.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + id, + tenant_id, + datasource_id, + create_time, + update_time + + + + std.id, + std.tenant_id, + std.datasource_id, + std.create_time, + std.update_time + + \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-biz/src/main/resources/mapper/SysTenantMapper.xml b/ballcat-tenant/ballcat-tenant-biz/src/main/resources/mapper/SysTenantMapper.xml new file mode 100644 index 000000000..a8970690e --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-biz/src/main/resources/mapper/SysTenantMapper.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + tenant_id, + tenant_code, + tenant_name, + url, + duty, + phone, + address, + logo, + status, + expire_time, + deleted, + create_time, + update_time + + + + st.tenant_id, + st.tenant_code, + st.tenant_name, + st.url, + st.duty, + st.phone, + st.address, + st.logo, + st.status, + st.expire_time, + st.deleted, + st.create_time, + st.update_time + + \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-controller/pom.xml b/ballcat-tenant/ballcat-tenant-controller/pom.xml new file mode 100644 index 000000000..7c9a9f3db --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-controller/pom.xml @@ -0,0 +1,28 @@ + + + + ballcat-tenant + com.hccake + ${revision} + + 4.0.0 + + ballcat-tenant-controller + + + + + + + com.hccake + ballcat-tenant-biz + + + com.hccake + ballcat-common-log + + + + \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-controller/src/main/java/com/hccake/ballcat/tenant/controller/SysDatasourceController.java b/ballcat-tenant/ballcat-tenant-controller/src/main/java/com/hccake/ballcat/tenant/controller/SysDatasourceController.java new file mode 100644 index 000000000..8b7786698 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-controller/src/main/java/com/hccake/ballcat/tenant/controller/SysDatasourceController.java @@ -0,0 +1,89 @@ +package com.hccake.ballcat.tenant.controller; + +import com.hccake.ballcat.common.log.operation.annotation.CreateOperationLogging; +import com.hccake.ballcat.common.log.operation.annotation.DeleteOperationLogging; +import com.hccake.ballcat.common.log.operation.annotation.UpdateOperationLogging; +import com.hccake.ballcat.common.model.domain.PageParam; +import com.hccake.ballcat.common.model.domain.PageResult; +import com.hccake.ballcat.common.model.result.BaseResultCode; +import com.hccake.ballcat.common.model.result.R; +import com.hccake.ballcat.tenant.model.entity.SysDatasource; +import com.hccake.ballcat.tenant.model.qo.SysDatasourceQO; +import com.hccake.ballcat.tenant.model.vo.SysDatasourcePageVO; +import com.hccake.ballcat.tenant.service.SysDatasourceService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * 数据源表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/tenant/sys-datasource") +@Api(value = "sys-datasource", tags = "数据源表管理") +public class SysDatasourceController { + + private final SysDatasourceService sysDatasourceService; + + /** + * 分页查询 + * @param pageParam 分页参数 + * @param sysDatasourceQO 数据源表查询对象 + * @return R 通用返回体 + */ + @ApiOperation(value = "分页查询", notes = "分页查询") + @GetMapping("/page") + @PreAuthorize("@per.hasPermission('tenant:sys-datasource:read')") + public R> getSysDatasourcePage(PageParam pageParam, + SysDatasourceQO sysDatasourceQO) { + return R.ok(sysDatasourceService.queryPage(pageParam, sysDatasourceQO)); + } + + /** + * 新增数据源表 + * @param sysDatasource 数据源表 + * @return R 通用返回体 + */ + @ApiOperation(value = "新增数据源表", notes = "新增数据源表") + @CreateOperationLogging(msg = "新增数据源表") + @PostMapping + @PreAuthorize("@per.hasPermission('tenant:sys-datasource:add')") + public R save(@RequestBody SysDatasource sysDatasource) { + return sysDatasourceService.save(sysDatasource) ? R.ok() + : R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "新增数据源表失败"); + } + + /** + * 修改数据源表 + * @param sysDatasource 数据源表 + * @return R 通用返回体 + */ + @ApiOperation(value = "修改数据源表", notes = "修改数据源表") + @UpdateOperationLogging(msg = "修改数据源表") + @PutMapping + @PreAuthorize("@per.hasPermission('tenant:sys-datasource:edit')") + public R updateById(@RequestBody SysDatasource sysDatasource) { + return sysDatasourceService.updateById(sysDatasource) ? R.ok() + : R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "修改数据源表失败"); + } + + /** + * 通过id删除数据源表 + * @param id id + * @return R 通用返回体 + */ + @ApiOperation(value = "通过id删除数据源表", notes = "通过id删除数据源表") + @DeleteOperationLogging(msg = "通过id删除数据源表") + @DeleteMapping("/{id}") + @PreAuthorize("@per.hasPermission('tenant:sys-datasource:del')") + public R removeById(@PathVariable("id") Long id) { + return sysDatasourceService.removeById(id) ? R.ok() + : R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "通过id删除数据源表失败"); + } + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-controller/src/main/java/com/hccake/ballcat/tenant/controller/SysTenantController.java b/ballcat-tenant/ballcat-tenant-controller/src/main/java/com/hccake/ballcat/tenant/controller/SysTenantController.java new file mode 100644 index 000000000..f154276d7 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-controller/src/main/java/com/hccake/ballcat/tenant/controller/SysTenantController.java @@ -0,0 +1,87 @@ +package com.hccake.ballcat.tenant.controller; + +import com.hccake.ballcat.common.log.operation.annotation.CreateOperationLogging; +import com.hccake.ballcat.common.log.operation.annotation.DeleteOperationLogging; +import com.hccake.ballcat.common.log.operation.annotation.UpdateOperationLogging; +import com.hccake.ballcat.common.model.domain.PageParam; +import com.hccake.ballcat.common.model.domain.PageResult; +import com.hccake.ballcat.common.model.result.BaseResultCode; +import com.hccake.ballcat.common.model.result.R; +import com.hccake.ballcat.tenant.model.entity.SysTenant; +import com.hccake.ballcat.tenant.model.qo.SysTenantQO; +import com.hccake.ballcat.tenant.model.vo.SysTenantPageVO; +import com.hccake.ballcat.tenant.service.SysTenantService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * 租户表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/tenant/sys-tenant") +@Api(value = "sys-tenant", tags = "租户表管理") +public class SysTenantController { + + private final SysTenantService sysTenantService; + + /** + * 分页查询 + * @param pageParam 分页参数 + * @param sysTenantQO 租户表查询对象 + * @return R 通用返回体 + */ + @ApiOperation(value = "分页查询", notes = "分页查询") + @GetMapping("/page") + @PreAuthorize("@per.hasPermission('tenant:sys-tenant:read')") + public R> getSysTenantPage(PageParam pageParam, SysTenantQO sysTenantQO) { + return R.ok(sysTenantService.queryPage(pageParam, sysTenantQO)); + } + + /** + * 新增租户表 + * @param sysTenant 租户表 + * @return R 通用返回体 + */ + @ApiOperation(value = "新增租户表", notes = "新增租户表") + @CreateOperationLogging(msg = "新增租户表") + @PostMapping + @PreAuthorize("@per.hasPermission('tenant:sys-tenant:add')") + public R save(@RequestBody SysTenant sysTenant) { + return sysTenantService.save(sysTenant) ? R.ok() : R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "新增租户表失败"); + } + + /** + * 修改租户表 + * @param sysTenant 租户表 + * @return R 通用返回体 + */ + @ApiOperation(value = "修改租户表", notes = "修改租户表") + @UpdateOperationLogging(msg = "修改租户表") + @PutMapping + @PreAuthorize("@per.hasPermission('tenant:sys-tenant:edit')") + public R updateById(@RequestBody SysTenant sysTenant) { + return sysTenantService.updateById(sysTenant) ? R.ok() + : R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "修改租户表失败"); + } + + /** + * 通过id删除租户表 + * @param tenantId id + * @return R 通用返回体 + */ + @ApiOperation(value = "通过id删除租户表", notes = "通过id删除租户表") + @DeleteOperationLogging(msg = "通过id删除租户表") + @DeleteMapping("/{tenantId}") + @PreAuthorize("@per.hasPermission('tenant:sys-tenant:del')") + public R removeById(@PathVariable("tenantId") Long tenantId) { + return sysTenantService.removeById(tenantId) ? R.ok() + : R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "通过id删除租户表失败"); + } + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-controller/src/main/java/com/hccake/ballcat/tenant/controller/SysTenantDatasourceController.java b/ballcat-tenant/ballcat-tenant-controller/src/main/java/com/hccake/ballcat/tenant/controller/SysTenantDatasourceController.java new file mode 100644 index 000000000..8d2ac48d6 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-controller/src/main/java/com/hccake/ballcat/tenant/controller/SysTenantDatasourceController.java @@ -0,0 +1,89 @@ +package com.hccake.ballcat.tenant.controller; + +import com.hccake.ballcat.common.log.operation.annotation.CreateOperationLogging; +import com.hccake.ballcat.common.log.operation.annotation.DeleteOperationLogging; +import com.hccake.ballcat.common.log.operation.annotation.UpdateOperationLogging; +import com.hccake.ballcat.common.model.domain.PageParam; +import com.hccake.ballcat.common.model.domain.PageResult; +import com.hccake.ballcat.common.model.result.BaseResultCode; +import com.hccake.ballcat.common.model.result.R; +import com.hccake.ballcat.tenant.model.entity.SysTenantDatasource; +import com.hccake.ballcat.tenant.model.qo.SysTenantDatasourceQO; +import com.hccake.ballcat.tenant.model.vo.SysTenantDatasourcePageVO; +import com.hccake.ballcat.tenant.service.SysTenantDatasourceService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * 租户数据源映射表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/tenant/sys-tenant-datasource") +@Api(value = "sys-tenant-datasource", tags = "租户数据源映射表管理") +public class SysTenantDatasourceController { + + private final SysTenantDatasourceService sysTenantDatasourceService; + + /** + * 分页查询 + * @param pageParam 分页参数 + * @param sysTenantDatasourceQO 租户数据源映射表查询对象 + * @return R 通用返回体 + */ + @ApiOperation(value = "分页查询", notes = "分页查询") + @GetMapping("/page") + @PreAuthorize("@per.hasPermission('tenant:sys-tenant-datasource:read')") + public R> getSysTenantDatasourcePage(PageParam pageParam, + SysTenantDatasourceQO sysTenantDatasourceQO) { + return R.ok(sysTenantDatasourceService.queryPage(pageParam, sysTenantDatasourceQO)); + } + + /** + * 新增租户数据源映射表 + * @param sysTenantDatasource 租户数据源映射表 + * @return R 通用返回体 + */ + @ApiOperation(value = "新增租户数据源映射表", notes = "新增租户数据源映射表") + @CreateOperationLogging(msg = "新增租户数据源映射表") + @PostMapping + @PreAuthorize("@per.hasPermission('tenant:sys-tenant-datasource:add')") + public R save(@RequestBody SysTenantDatasource sysTenantDatasource) { + return sysTenantDatasourceService.save(sysTenantDatasource) ? R.ok() + : R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "新增租户数据源映射表失败"); + } + + /** + * 修改租户数据源映射表 + * @param sysTenantDatasource 租户数据源映射表 + * @return R 通用返回体 + */ + @ApiOperation(value = "修改租户数据源映射表", notes = "修改租户数据源映射表") + @UpdateOperationLogging(msg = "修改租户数据源映射表") + @PutMapping + @PreAuthorize("@per.hasPermission('tenant:sys-tenant-datasource:edit')") + public R updateById(@RequestBody SysTenantDatasource sysTenantDatasource) { + return sysTenantDatasourceService.updateById(sysTenantDatasource) ? R.ok() + : R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "修改租户数据源映射表失败"); + } + + /** + * 通过id删除租户数据源映射表 + * @param id id + * @return R 通用返回体 + */ + @ApiOperation(value = "通过id删除租户数据源映射表", notes = "通过id删除租户数据源映射表") + @DeleteOperationLogging(msg = "通过id删除租户数据源映射表") + @DeleteMapping("/{id}") + @PreAuthorize("@per.hasPermission('tenant:sys-tenant-datasource:del')") + public R removeById(@PathVariable("id") Long id) { + return sysTenantDatasourceService.removeById(id) ? R.ok() + : R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "通过id删除租户数据源映射表失败"); + } + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-model/pom.xml b/ballcat-tenant/ballcat-tenant-model/pom.xml new file mode 100644 index 000000000..b0a7d6d1f --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/pom.xml @@ -0,0 +1,36 @@ + + + + ballcat-tenant + com.hccake + ${revision} + + 4.0.0 + + ballcat-tenant-model + + + + + + + io.swagger + swagger-annotations + + + com.baomidou + mybatis-plus-annotation + + + javax.validation + validation-api + + + com.hccake + ballcat-extend-mybatis-plus + + + + \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/converter/SysDatasourceConverter.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/converter/SysDatasourceConverter.java new file mode 100644 index 000000000..ee5f21014 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/converter/SysDatasourceConverter.java @@ -0,0 +1,25 @@ +package com.hccake.ballcat.tenant.converter; + +import com.hccake.ballcat.tenant.model.entity.SysDatasource; +import com.hccake.ballcat.tenant.model.vo.SysDatasourcePageVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 数据源表模型转换器 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Mapper +public interface SysDatasourceConverter { + + SysDatasourceConverter INSTANCE = Mappers.getMapper(SysDatasourceConverter.class); + + /** + * PO 转 PageVO + * @param sysDatasource 数据源表 + * @return SysDatasourcePageVO 数据源表PageVO + */ + SysDatasourcePageVO poToPageVo(SysDatasource sysDatasource); + +} diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/converter/SysTenantConverter.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/converter/SysTenantConverter.java new file mode 100644 index 000000000..c183b79f1 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/converter/SysTenantConverter.java @@ -0,0 +1,25 @@ +package com.hccake.ballcat.tenant.converter; + +import com.hccake.ballcat.tenant.model.entity.SysTenant; +import com.hccake.ballcat.tenant.model.vo.SysTenantPageVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 租户表模型转换器 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Mapper +public interface SysTenantConverter { + + SysTenantConverter INSTANCE = Mappers.getMapper(SysTenantConverter.class); + + /** + * PO 转 PageVO + * @param sysTenant 租户表 + * @return SysTenantPageVO 租户表PageVO + */ + SysTenantPageVO poToPageVo(SysTenant sysTenant); + +} diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/converter/SysTenantDatasourceConverter.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/converter/SysTenantDatasourceConverter.java new file mode 100644 index 000000000..84ec7f999 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/converter/SysTenantDatasourceConverter.java @@ -0,0 +1,25 @@ +package com.hccake.ballcat.tenant.converter; + +import com.hccake.ballcat.tenant.model.entity.SysTenantDatasource; +import com.hccake.ballcat.tenant.model.vo.SysTenantDatasourcePageVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 租户数据源映射表模型转换器 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Mapper +public interface SysTenantDatasourceConverter { + + SysTenantDatasourceConverter INSTANCE = Mappers.getMapper(SysTenantDatasourceConverter.class); + + /** + * PO 转 PageVO + * @param sysTenantDatasource 租户数据源映射表 + * @return SysTenantDatasourcePageVO 租户数据源映射表PageVO + */ + SysTenantDatasourcePageVO poToPageVo(SysTenantDatasource sysTenantDatasource); + +} diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/enums/TenantStatusEnum.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/enums/TenantStatusEnum.java new file mode 100644 index 000000000..d0e44ef65 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/enums/TenantStatusEnum.java @@ -0,0 +1,28 @@ +package com.hccake.ballcat.tenant.enums; + +/** + * @author huyuanzhi + */ + +public enum TenantStatusEnum { + + /** + * 正常 + */ + ENABLE(1), + /** + * 禁用 + */ + DISABLE(0); + + private final int status; + + TenantStatusEnum(int status) { + this.status = status; + } + + public int getStatus() { + return status; + } + +} diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/entity/SysDatasource.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/entity/SysDatasource.java new file mode 100644 index 000000000..9d9d3eda9 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/entity/SysDatasource.java @@ -0,0 +1,93 @@ +package com.hccake.ballcat.tenant.model.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.time.LocalDateTime; + +/** + * 数据源表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Data +@TableName("sys_datasource") +@ApiModel(value = "数据源表") +public class SysDatasource { + + private static final long serialVersionUID = 1L; + + /** + * + */ + @TableId + @ApiModelProperty(value = "") + private Long id; + + /** + * 数据源名称 + */ + @ApiModelProperty(value = "数据源名称") + private String name; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址") + private String url; + + /** + * 用户名 + */ + @ApiModelProperty(value = "用户名") + private String username; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码") + private String password; + + /** + * 类型 + */ + @ApiModelProperty(value = "类型") + private Integer type; + + /** + * + */ + @ApiModelProperty(value = "") + private Integer maxHolds; + + /** + * 额外信息 + */ + @ApiModelProperty(value = "额外信息") + private String extra; + + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + private String description; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @ApiModelProperty(value = "创建时间") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @ApiModelProperty(value = "更新时间") + private LocalDateTime updateTime; + +} diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/entity/SysTenant.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/entity/SysTenant.java new file mode 100644 index 000000000..baa9208d7 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/entity/SysTenant.java @@ -0,0 +1,105 @@ +package com.hccake.ballcat.tenant.model.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.time.LocalDateTime; + +/** + * 租户表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Data +@TableName("sys_tenant") +@ApiModel(value = "租户表") +public class SysTenant { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId + @ApiModelProperty(value = "主键") + private Long tenantId; + + /** + * 租户code + */ + @ApiModelProperty(value = "租户code") + private String tenantCode; + + /** + * 租户名称 + */ + @ApiModelProperty(value = "租户名称") + private String tenantName; + + /** + * 域名地址 + */ + @ApiModelProperty(value = "域名地址") + private String url; + + /** + * 联系人 + */ + @ApiModelProperty(value = "联系人") + private String duty; + + /** + * 联系电话 + */ + @ApiModelProperty(value = "联系电话") + private String phone; + + /** + * 联系地址 + */ + @ApiModelProperty(value = "联系地址") + private String address; + + /** + * logo地址 + */ + @ApiModelProperty(value = "logo地址") + private String logo; + + /** + * 状态(1-正常,0-冻结) + */ + @ApiModelProperty(value = "状态(1-正常,0-冻结)") + private Integer status; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间") + private LocalDateTime expireTime; + + /** + * 逻辑删除标识,未删除为 0,已删除为删除时间 + */ + @ApiModelProperty(value = "逻辑删除标识,未删除为 0,已删除为删除时间") + private Long deleted; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @ApiModelProperty(value = "创建时间") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @ApiModelProperty(value = "更新时间") + private LocalDateTime updateTime; + +} diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/entity/SysTenantDatasource.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/entity/SysTenantDatasource.java new file mode 100644 index 000000000..f22579c1c --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/entity/SysTenantDatasource.java @@ -0,0 +1,57 @@ +package com.hccake.ballcat.tenant.model.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.time.LocalDateTime; + +/** + * 租户数据源映射表 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Data +@TableName("sys_tenant_datasource") +@ApiModel(value = "租户数据源映射表") +public class SysTenantDatasource { + + private static final long serialVersionUID = 1L; + + /** + * + */ + @TableId + @ApiModelProperty(value = "") + private Long id; + + /** + * + */ + @ApiModelProperty(value = "") + private Long tenantId; + + /** + * + */ + @ApiModelProperty(value = "") + private Long datasourceId; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @ApiModelProperty(value = "创建时间") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @ApiModelProperty(value = "更新时间") + private LocalDateTime updateTime; + +} diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/qo/SysDatasourceQO.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/qo/SysDatasourceQO.java new file mode 100644 index 000000000..260a69953 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/qo/SysDatasourceQO.java @@ -0,0 +1,24 @@ +package com.hccake.ballcat.tenant.model.qo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 数据源表 查询对象 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Data +@ApiModel(value = "数据源表查询对象") +public class SysDatasourceQO { + + private static final long serialVersionUID = 1L; + + /** + * + */ + @ApiModelProperty(value = "") + private Long id; + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/qo/SysTenantDatasourceQO.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/qo/SysTenantDatasourceQO.java new file mode 100644 index 000000000..7c37491dd --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/qo/SysTenantDatasourceQO.java @@ -0,0 +1,24 @@ +package com.hccake.ballcat.tenant.model.qo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 租户数据源映射表 查询对象 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Data +@ApiModel(value = "租户数据源映射表查询对象") +public class SysTenantDatasourceQO { + + private static final long serialVersionUID = 1L; + + /** + * + */ + @ApiModelProperty(value = "") + private Long id; + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/qo/SysTenantQO.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/qo/SysTenantQO.java new file mode 100644 index 000000000..3c2600468 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/qo/SysTenantQO.java @@ -0,0 +1,24 @@ +package com.hccake.ballcat.tenant.model.qo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 租户表 查询对象 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Data +@ApiModel(value = "租户表查询对象") +public class SysTenantQO { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @ApiModelProperty(value = "主键") + private Long tenantId; + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/vo/SysDatasourcePageVO.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/vo/SysDatasourcePageVO.java new file mode 100644 index 000000000..784c8ac7d --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/vo/SysDatasourcePageVO.java @@ -0,0 +1,85 @@ +package com.hccake.ballcat.tenant.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.time.LocalDateTime; + +/** + * 数据源表分页视图对象 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Data +@ApiModel(value = "数据源表分页视图对象") +public class SysDatasourcePageVO { + + private static final long serialVersionUID = 1L; + + /** + * + */ + @ApiModelProperty(value = "") + private Long id; + + /** + * 数据源名称 + */ + @ApiModelProperty(value = "数据源名称") + private String name; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址") + private String url; + + /** + * 用户名 + */ + @ApiModelProperty(value = "用户名") + private String username; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码") + private String password; + + /** + * 类型 + */ + @ApiModelProperty(value = "类型") + private Integer type; + + /** + * + */ + @ApiModelProperty(value = "") + private Integer maxHolds; + + /** + * 额外信息 + */ + @ApiModelProperty(value = "额外信息") + private String extra; + + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + private String description; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @ApiModelProperty(value = "更新时间") + private LocalDateTime updateTime; + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/vo/SysTenantDatasourcePageVO.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/vo/SysTenantDatasourcePageVO.java new file mode 100644 index 000000000..3e7695d60 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/vo/SysTenantDatasourcePageVO.java @@ -0,0 +1,49 @@ +package com.hccake.ballcat.tenant.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.time.LocalDateTime; + +/** + * 租户数据源映射表分页视图对象 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Data +@ApiModel(value = "租户数据源映射表分页视图对象") +public class SysTenantDatasourcePageVO { + + private static final long serialVersionUID = 1L; + + /** + * + */ + @ApiModelProperty(value = "") + private Long id; + + /** + * + */ + @ApiModelProperty(value = "") + private Long tenantId; + + /** + * + */ + @ApiModelProperty(value = "") + private Long datasourceId; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @ApiModelProperty(value = "更新时间") + private LocalDateTime updateTime; + +} \ No newline at end of file diff --git a/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/vo/SysTenantPageVO.java b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/vo/SysTenantPageVO.java new file mode 100644 index 000000000..4a8a117b8 --- /dev/null +++ b/ballcat-tenant/ballcat-tenant-model/src/main/java/com/hccake/ballcat/tenant/model/vo/SysTenantPageVO.java @@ -0,0 +1,97 @@ +package com.hccake.ballcat.tenant.model.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.time.LocalDateTime; + +/** + * 租户表分页视图对象 + * + * @author huyuanzhi 2021-12-15 21:33:42 + */ +@Data +@ApiModel(value = "租户表分页视图对象") +public class SysTenantPageVO { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @ApiModelProperty(value = "主键") + private Long tenantId; + + /** + * 租户code + */ + @ApiModelProperty(value = "租户code") + private String tenantCode; + + /** + * 租户名称 + */ + @ApiModelProperty(value = "租户名称") + private String tenantName; + + /** + * 域名地址 + */ + @ApiModelProperty(value = "域名地址") + private String url; + + /** + * 联系人 + */ + @ApiModelProperty(value = "联系人") + private String duty; + + /** + * 联系电话 + */ + @ApiModelProperty(value = "联系电话") + private String phone; + + /** + * 联系地址 + */ + @ApiModelProperty(value = "联系地址") + private String address; + + /** + * logo地址 + */ + @ApiModelProperty(value = "logo地址") + private String logo; + + /** + * 状态(1-正常,0-冻结) + */ + @ApiModelProperty(value = "状态(1-正常,0-冻结)") + private Integer status; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间") + private LocalDateTime expireTime; + + /** + * 逻辑删除标识,未删除为 0,已删除为删除时间 + */ + @ApiModelProperty(value = "逻辑删除标识,未删除为 0,已删除为删除时间") + private Long deleted; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @ApiModelProperty(value = "更新时间") + private LocalDateTime updateTime; + +} \ No newline at end of file diff --git a/ballcat-tenant/pom.xml b/ballcat-tenant/pom.xml new file mode 100644 index 000000000..204447c87 --- /dev/null +++ b/ballcat-tenant/pom.xml @@ -0,0 +1,24 @@ + + + + ballcat + com.hccake + ${revision} + + 4.0.0 + + ballcat-tenant + pom + + ballcat-tenant-biz + ballcat-tenant-controller + ballcat-tenant-model + + + + + + + \ No newline at end of file diff --git a/doc/update_sql/tenant.sql b/doc/update_sql/tenant.sql new file mode 100644 index 000000000..c23f354c7 --- /dev/null +++ b/doc/update_sql/tenant.sql @@ -0,0 +1,48 @@ +CREATE TABLE `sys_datasource` ( + `id` bigint(64) NOT NULL, + `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '数据源名称', + `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '地址', + `username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名', + `password` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码', + `type` int(1) NOT NULL COMMENT '类型', + `max_holds` tinyint(2) DEFAULT NULL, + `extra` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '额外信息', + `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '描述', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='数据源表'; + +-- ---------------------------- +-- Table structure for sys_tenant +-- ---------------------------- +CREATE TABLE `sys_tenant` ( + `tenant_id` bigint(64) NOT NULL COMMENT '主键', + `tenant_code` varchar(16) COLLATE utf8mb4_general_ci NOT NULL COMMENT '租户code', + `tenant_name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT '租户名称', + `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '域名地址', + `duty` varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '联系人', + `phone` varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '联系电话', + `address` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '联系地址', + `logo` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'logo地址', + `status` tinyint(1) DEFAULT NULL COMMENT '状态(1-正常,0-冻结)', + `expire_time` date DEFAULT NULL COMMENT '创建时间', + `deleted` bigint(20) DEFAULT NULL COMMENT '逻辑删除标识,未删除为 0,已删除为删除时间', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`tenant_id`) USING BTREE, + UNIQUE KEY `idx_tenant_code` (`tenant_code`), + UNIQUE KEY `idx_tenant_name` (`tenant_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='租户表'; + +-- ---------------------------- +-- Table structure for sys_tenant_datasource +-- ---------------------------- +CREATE TABLE `sys_tenant_datasource` ( + `id` bigint(64) NOT NULL, + `tenant_id` bigint(64) NOT NULL, + `datasource_id` bigint(64) NOT NULL, + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='租户数据源映射表'; diff --git a/pom.xml b/pom.xml index 30e0130ad..19ec0615f 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ ballcat-notify ballcat-log ballcat-i18n + ballcat-tenant ballcat 项目基本脚手架