当前位置:   article > 正文

多租户设计

多租户

目录

一、多租户是什么?

二、多租户数据隔离方案

三、实现步骤

1.引入库

2.配置文件 META-INF/spring.factories

3.TenantConfiguration

4.TenantProperties

5.TenantHandler

6.TenantInterceptor

7.MybatisPlusProperties

8.MybatisAutoConfiguration

9.引用租户模块

总结


一、多租户是什么?

• 多租户技术是一种软件架构技术,是实现如何在多用户(一般是面向企业用户)的环境下共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。

• 多租户技术可以实现多个租户之间共享系统实例,同时又可以实现租户的系统实例的个性化定制。

• 通过在多个租户之间的资源复用,有效节省开发应用的成本。在租户之间共享应用程序的单个实例,可以实现当应用程序升级时,所有租户可以同时升级。

二、多租户数据隔离方案

• 独立数据库

• 共享数据库,隔离数据架构

• 共享数据库,共享数据架构

 采用方案:共享数据库,共享数据架构(租户ID隔离)

三、实现步骤

1.引入库

<!--mybatis-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>

<!--数据库-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

<!--dynamic-datasource-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>

2.配置文件 META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.ronshi.common.tenant.config.TenantConfiguration

3.TenantConfiguration

  1. @Configuration(proxyBeanMethods = false)
  2. @AutoConfigureBefore({MybatisAutoConfiguration.class})
  3. @EnableConfigurationProperties({TenantProperties.class})
  4. public class TenantConfiguration {
  5. @Bean
  6. @ConditionalOnMissingBean({TenantLineHandler.class})
  7. public TenantLineHandler tenantHandler(TenantProperties tenantProperties) {
  8. return new TenantHandler(tenantProperties);
  9. }
  10. @Bean
  11. @ConditionalOnMissingBean({TenantLineInnerInterceptor.class})
  12. public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantLineHandler tenantHandler, TenantProperties tenantProperties) {
  13. TenantInterceptor tenantInterceptor = new TenantInterceptor();
  14. tenantInterceptor.setTenantLineHandler(tenantHandler);
  15. tenantInterceptor.setTenantProperties(tenantProperties);
  16. return tenantInterceptor;
  17. }
  18. }

4.TenantProperties

  1. @Data
  2. @ConfigurationProperties(prefix = "ronshi.tenant")
  3. public class TenantProperties {
  4. private Boolean enhance;
  5. private String column;
  6. private List<String> excludeTables;
  7. private List<String> matchUrls;
  8. private List<String> excludeUrls;
  9. public TenantProperties() {
  10. this.enhance = Boolean.FALSE;
  11. this.column = "tenant_id";
  12. this.excludeTables = new ArrayList<>();
  13. this.matchUrls = new ArrayList<>();
  14. matchUrls.add("/**");
  15. this.excludeUrls = new ArrayList<>();
  16. }
  17. }

5.TenantHandler

  1. public class TenantHandler implements TenantLineHandler, SmartInitializingSingleton {
  2. private final TenantProperties tenantProperties;
  3. @Override
  4. public Expression getTenantId() {
  5. Long tenantId = TenantUtil.getTenantId();
  6. if (tenantId == null) {
  7. throw new RuntimeException("请设置租户ID");
  8. }
  9. return new LongValue(tenantId);
  10. }
  11. @Override
  12. public String getTenantIdColumn() {
  13. return this.tenantProperties.getColumn();
  14. }
  15. @Override
  16. public boolean ignoreTable(String tableName) {
  17. return this.tenantProperties.getExcludeTables().contains(tableName);
  18. }
  19. @Override
  20. public void afterSingletonsInstantiated() {
  21. // 实例化后执行
  22. }
  23. public TenantHandler(final TenantProperties tenantProperties) {
  24. this.tenantProperties = tenantProperties;
  25. }
  26. }

6.TenantInterceptor

  1. @Data
  2. public class TenantInterceptor extends TenantLineInnerInterceptor {
  3. private TenantProperties tenantProperties;
  4. }

7.MybatisPlusProperties

  1. @ConfigurationProperties(prefix = "ronshi.mybatis-plus")
  2. @Data
  3. public class MybatisPlusProperties {
  4. private Boolean tenantMode = false;
  5. }

8.MybatisAutoConfiguration

  1. @Configuration(proxyBeanMethods = false)
  2. @EnableConfigurationProperties({MybatisPlusProperties.class})
  3. public class MybatisAutoConfiguration {
  4. @Bean
  5. @ConditionalOnMissingBean({TenantLineHandler.class})
  6. public TenantLineHandler tenantLineHandler() {
  7. return new TenantLineHandler() {
  8. @Override
  9. public Expression getTenantId() {
  10. return new LongValue(0L);
  11. }
  12. @Override
  13. public boolean ignoreTable(String tableName) {
  14. return true;
  15. }
  16. };
  17. }
  18. @Bean
  19. @ConditionalOnMissingBean({TenantLineInnerInterceptor.class})
  20. public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantLineHandler tenantHandler) {
  21. return new TenantLineInnerInterceptor(tenantHandler);
  22. }
  23. /**
  24. * 插件主体
  25. *
  26. * @return MybatisPlusInterceptor
  27. */
  28. @Bean
  29. public MybatisPlusInterceptor mybatisPlusInterceptor(TenantLineInnerInterceptor tenantLineInnerInterceptor, MybatisPlusProperties mybatisPlusProperties) {
  30. MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  31. //判断是否为租户模式
  32. if (Boolean.TRUE.equals(mybatisPlusProperties.getTenantMode())) {
  33. interceptor.addInnerInterceptor(tenantLineInnerInterceptor);
  34. }
  35. interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
  36. return interceptor;
  37. }
  38. }

9.引用租户模块

  1. <!--多租户数据隔离 模块-->
  2. <dependency>
  3. <groupId>com.ronshi</groupId>
  4. <artifactId>tenant-starter</artifactId>
  5. </dependency>
  1. ronshi:
  2. mybatis-plus:
  3. tenant-mode: true
  4. tenant:
  5. exclude-tables:
  6. - tenant

总结

租户模块分包,可根据服务是否为多租户模式,来选择是否加载租户模块。租户字段名称和拦截的表名动态配置。采用了配置属性类、配置类、拦截类、处理类分离的模式,可以灵活扩展。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/902978
推荐阅读
相关标签
  

闽ICP备14008679号