springboot项⽬多租户实现
公司规划了⼀个AIOT平台项⽬,希望将来可以提供SAAS服务,可设备接⼊、算法训练及算法接⼝发布。写此博⽂时,本⼈已经实现了IOT 部分,多租户不同设备接⼊以及设备数据转发。本⽂着重介绍项⽬中多租户实现。主流的租户实现⼀般有两种⽅式,⼀种是所有表字段冗余租户ID字段,在增删改查时拦截sql语句进⾏拼接租户ID字段,达到不同租户展⽰不同数据的⽬录;另⼀种⽅式每个租户对应⼀个业务逻辑库,增删改查映射到租户对应的业务库,达到多租户效果。本⼈采⽤了第⼆种实现⽅式,不多说,直接上代码。
1、实现涉及技术及框架
springboot+nacos+redis+shardingjdbc(5.0.0-beta)+mysql
2、实现原理
a)项⽬实施:初始化iot库,为租户管理库,只存储租户相关信息,sysadmin可登录创建租户
b)项⽬启动:获取租户信息、动态创建已有租户数据源、存储有效数据源别名到redis,发布数源到nacos、创建数据源nacos(从nacos监听数据源变化,更新最新数据源并别名写到redis,部署多个实例保持数据源⼀致)
b)新增租户:创建租户库并执⾏初始化脚本、插⼊租户库租户信息、更新shardingjdbc数据源、写⼊有效数据源别名到redis、发布数据源到nacos,其他实例监听nacos创建新的数据源、写⼊iot库租户信息
c)删除租户:删除iot库租户信息、删除redis缓存数据源别名、删除本地数据源、发布数据源到nacos,其他实例监听nacos删除数据源、删除租户库
d)租户登录增删改查:通过sharding-jdbc分库中间件,切⾯service,在执⾏sql时获取登录⽤户的租户ID,通过⾃定义的分库策略,切换到对应租户业务库执⾏sql
3、代码实现
1)l⽂件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd">
<parent>
<groupId&andhonor</groupId>
<artifactId>iot-user</artifactId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>iot-user-biz</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId&andhonor</groupId>
<artifactId>iot-user-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId&andhonor</groupId>
<artifactId>iot-user-auth</artifactId>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>            <version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.jeecgframework</groupId>
<artifactId>autopoi</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.jeecgframework</groupId>
<artifactId>autopoi-web</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>codegenerate</artifactId>
<version>1.3.2</version>
</dependency>
<!-- druid 数据源,⼀定不能⽤druid-spring-boot-starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!--⼀定不能引⼊dynamic-datasource-spring-boot-starter包-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>            <version>5.0.0-beta</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<groupId&andhonor.framework.boot</groupId>
<artifactId>base-tools</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.6.Final</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
<dependency>
<groupId>org.jeecgframework</groupId>
springboot推荐算法<artifactId>jeewx-api</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>3.12.2</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>dev</id>
<activation>
<!--默认激活配置-->
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<!--当前环境-->
<profile.name>dev</profile.name>
<!--配置⽂件前缀-->
<prefix.name></prefix.name>
<!--连接nacos⽤户名-->
<config.nacos.username>nacos</config.nacos.username>                <!--连接nacos密码-->
<config.nacos.passwd>nacos</config.nacos.passwd>
<!--Nacos配置中⼼地址-->
<config.server-addr>127.0.0.1:8868</config.server-addr>
<!--Nacos配置中⼼命名空间,⽤于⽀持多环境.这⾥必须使⽤ID,不能使⽤名称,默认为空-->                <config.namespace>iot</config.namespace>
<!--Nacos配置分组名称-->
&up>DEFAULT_GROUP</up>
<!--Nacos服务发现地址-->
<discovery.server-addr>127.0.0.1:8868</discovery.server-addr>
</properties>
</profile>
</profiles>
<build>
<finalName>iot-user-biz</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2)l的分库配置
spring:
shardingsphere:
enabled: true
datasource:
#指定数据源名称可以⾃定义,注意:名称要跟后⾯的配置⼀致
names: ds0
#ds0为租户管理库,租户库动态⽣成
ds0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-nam: sql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/iot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTim        username: root
password: grandhonor_db
rules:
sharding:
#绑定表规则列表,多个以逗号分割
binding-tables[6]: biz_device,sys_area
tables:
tenant_user:
actual-data-nodes: ds$->{0..999}.sys_tenant_user
database-strategy:
hint:
sharding-algorithm-name: database-defaults
device:
actual-data-nodes: ds$->{0..999}.biz_device
default-database-strategy:
hint:
sharding-algorithm-name: database-tenant
default-table-strategy:
none:
#分库或者分表算法配置
sharding-algorithms:
database-tenant:
type: CLASS_BASED
props:
strategy: HINT
algorithmClassName: andhonor.ant.sharding.DatabaseShardingAlgorithm
database-defaults:
type: CLASS_BASED
props:
strategy: HINT
algorithmClassName: andhonor.ant.sharding.DefaultShardingAlgorithm
props:
#是否输出sql
sql-show: true
说明:涉及隐私,只截取两个表显⽰,使⽤⾃定义分库策略
3)l