diff --git a/kernel-d-db/db-api/src/main/java/cn/stylefeng/roses/kernel/db/api/pojo/tenant/TenantTableProperties.java b/kernel-d-db/db-api/src/main/java/cn/stylefeng/roses/kernel/db/api/pojo/tenant/TenantTableProperties.java new file mode 100644 index 000000000..33beda7b5 --- /dev/null +++ b/kernel-d-db/db-api/src/main/java/cn/stylefeng/roses/kernel/db/api/pojo/tenant/TenantTableProperties.java @@ -0,0 +1,45 @@ +/* + * Copyright [2020-2030] [https://www.stylefeng.cn] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Guns源码头部的版权声明。 + * 3.请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns + * 5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns + * 6.若您的项目无法满足以上几点,可申请商业授权 + */ +package cn.stylefeng.roses.kernel.db.api.pojo.tenant; + +import lombok.Data; + +import java.util.List; + +/** + * 租户相关的表配置 + * + * @author fengshuonan + * @since 2023/8/30 10:37 + */ +@Data +public class TenantTableProperties { + + /** + * 涉及到租户业务的表集合 + */ + private List businessTableList; + +} diff --git a/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/ProjectTenantInterceptor.java b/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/ProjectTenantInterceptor.java new file mode 100644 index 000000000..e75b5eded --- /dev/null +++ b/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/ProjectTenantInterceptor.java @@ -0,0 +1,69 @@ +package cn.stylefeng.roses.kernel.db.mp.tenant; + +import cn.hutool.core.util.ObjectUtil; +import cn.stylefeng.roses.kernel.auth.api.context.LoginContext; +import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser; +import cn.stylefeng.roses.kernel.db.api.pojo.tenant.TenantTableProperties; +import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.LongValue; +import net.sf.jsqlparser.schema.Column; + +import java.util.List; + +/** + * 租户隔离插件 + * + * @author fengshuonan + * @since 2023/8/30 10:14 + */ +public class ProjectTenantInterceptor implements TenantLineHandler { + + /** + * 租户相关的表的配置 + */ + private TenantTableProperties tenantTableProperties; + + public ProjectTenantInterceptor(TenantTableProperties tenantTableProperties) { + this.tenantTableProperties = tenantTableProperties; + } + + @Override + public Expression getTenantId() { + LoginUser loginUserNullable = LoginContext.me().getLoginUserNullable(); + if (loginUserNullable == null) { + return null; + } + if (ObjectUtil.isEmpty(loginUserNullable.getTenantId())) { + return null; + } + return new LongValue(loginUserNullable.getTenantId()); + } + + @Override + public boolean ignoreTable(String tableName) { + + if (tenantTableProperties == null) { + return true; + } + + List businessTableList = tenantTableProperties.getBusinessTableList(); + if (ObjectUtil.isEmpty(businessTableList)) { + return true; + } + + for (String tenantTable : businessTableList) { + if (tenantTable.equalsIgnoreCase(tableName)) { + return false; + } + } + + return true; + } + + @Override + public boolean ignoreInsert(List columns, String tenantIdColumn) { + return TenantLineHandler.super.ignoreInsert(columns, tenantIdColumn); + } + +} diff --git a/kernel-d-db/db-spring-boot-starter/pom.xml b/kernel-d-db/db-spring-boot-starter/pom.xml index c686c0bc2..19e38254d 100644 --- a/kernel-d-db/db-spring-boot-starter/pom.xml +++ b/kernel-d-db/db-spring-boot-starter/pom.xml @@ -31,6 +31,12 @@ ${roses.version} + + + org.springframework.boot + spring-boot-configuration-processor + + diff --git a/kernel-d-db/db-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/db/starter/ProjectMyBatisPlusAutoConfiguration.java b/kernel-d-db/db-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/db/starter/ProjectMyBatisPlusAutoConfiguration.java index 09d119fca..279be94e0 100644 --- a/kernel-d-db/db-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/db/starter/ProjectMyBatisPlusAutoConfiguration.java +++ b/kernel-d-db/db-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/db/starter/ProjectMyBatisPlusAutoConfiguration.java @@ -24,15 +24,20 @@ */ package cn.stylefeng.roses.kernel.db.starter; +import cn.stylefeng.roses.kernel.db.api.pojo.tenant.TenantTableProperties; import cn.stylefeng.roses.kernel.db.mp.dbid.CustomDatabaseIdProvider; import cn.stylefeng.roses.kernel.db.mp.fieldfill.CustomMetaObjectHandler; import cn.stylefeng.roses.kernel.db.mp.injector.CustomInsertBatchSqlInjector; +import cn.stylefeng.roses.kernel.db.mp.tenant.ProjectTenantInterceptor; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -46,6 +51,19 @@ import org.springframework.context.annotation.Configuration; @AutoConfigureBefore(MybatisPlusAutoConfiguration.class) public class ProjectMyBatisPlusAutoConfiguration { + /** + * 设置租户的表的集合,在yml配置中配置 tenant.businessTableList + * + * @author fengshuonan + * @since 2023/8/30 10:39 + */ + @Bean + @ConfigurationProperties(prefix = "tenant") + @ConditionalOnMissingBean(TenantTableProperties.class) + public TenantTableProperties tenantTableProperties() { + return new TenantTableProperties(); + } + /** * 新的分页插件 * @@ -53,9 +71,12 @@ public class ProjectMyBatisPlusAutoConfiguration { * @since 2020/12/24 13:13 */ @Bean - public MybatisPlusInterceptor mybatisPlusInterceptor() { + public MybatisPlusInterceptor mybatisPlusInterceptor(TenantTableProperties tenantTableProperties) { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 使用多租户插件 + interceptor.addInnerInterceptor(tenantLineInnerInterceptor(tenantTableProperties)); + // 使用分页插插件 interceptor.addInnerInterceptor(paginationInterceptor()); @@ -110,7 +131,7 @@ public class ProjectMyBatisPlusAutoConfiguration { } /** - * 自定义sqlInjector + * 自定义sqlInjector,针对批量插入优化 * * @author fengshuonan * @since 2022/9/17 14:28 @@ -120,4 +141,15 @@ public class ProjectMyBatisPlusAutoConfiguration { return new CustomInsertBatchSqlInjector(); } + /** + * 多租户插件 + * + * @author fengshuonan + * @since 2023/8/30 10:17 + */ + @Bean + public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantTableProperties tenantTableProperties) { + return new TenantLineInnerInterceptor(new ProjectTenantInterceptor(tenantTableProperties)); + } + }