Spring动态注册多数据源

本文详细介绍了在SaaS应用中,如何在单实例多schema的数据库架构下,实现Spring动态增删和切换数据源。通过TenantConfigEntity记录租户信息,使用DynamicDataSource和DynamicDataSourceSummoner动态加载数据源,结合DataSourceUtil和DataSourceContextHolder实现线程上下文中的数据源切换。此外,通过AOP的DynamicDataSourceAspectAdvice自动切换数据源,确保请求根据租户信息选择正确数据源。
摘要由CSDN通过智能技术生成

前言

最近在做SaaS应用,数据库采用了单实例多schema的架构,每个租户有一个独立的schema,同时整个数据源有一个共享的schema,因此需要解决动态增删、切换数据源的问题。

在网上搜了很多文章后,很多都是讲主从数据源配置,或都是在应用启动前已经确定好数据源配置的,甚少讲在不停机的情况如何动态加载数据源,所以写下这篇文章,以供参考。

使用到的技术

  • Java8
  • Spring + SpringMVC + MyBatis
  • Druid连接池
  • Lombok
  • (以上技术并不影响思路实现,只是为了方便浏览以下代码片段)

思路

当一个请求进来的时候,判断当前用户所属租户,并根据租户信息切换至相应数据源,然后进行后续的业务操作。

代码实现

TenantConfigEntity(租户信息)

@EqualsAndHashCode(callSuper = false)
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class TenantConfigEntity {
    /**
     * 租户id
     **/
    Integer tenantId;
    /**
     * 租户名称
     **/
    String tenantName;
    /**
     * 租户名称key
     **/
    String tenantKey;
    /**
     * 数据库url
     **/
    String dbUrl;
    /**
     * 数据库用户名
     **/
    String dbUser;
    /**
     * 数据库密码
     **/
    String dbPassword;
    /**
     * 数据库public_key
     **/
    String dbPublicKey;
}

DataSourceUtil(辅助工具类,非必要)

public class DataSourceUtil {

    private static final String DATA_SOURCE_BEAN_KEY_SUFFIX = "_data_source";

    private static final String JDBC_URL_ARGS = "?useUnicode=true&characterEncoding=UTF-8&useOldAliasMetadataBehavior=true&zeroDateTimeBehavior=convertToNull";

    private static final String CONNECTION_PROPERTIES = "config.decrypt=true;config.decrypt.key=";
    /**
     * 拼接数据源的spring bean key
     */
    public static String getDataSourceBeanKey(String tenantKey) {
        if (!StringUtils.hasText(tenantKey)) {
            return null;
        }
        return tenantKey + DATA_SOURCE_BEAN_KEY_SUFFIX;
    }
    /**
     * 拼接完整的JDBC URL
     */
    public static String getJDBCUrl(String baseUrl) {
        if (!StringUtils.hasText(baseUrl)) {
            return null;
        }
        return baseUrl + JDBC_URL_ARGS;
    }
    /**
     * 拼接完整的Druid连接属性
     */
    public static String getConnectionProperties(String publicKey) {
        if (!StringUtils.hasText(publicKey)) {
            return null;
        }
        return CONNECTION_PROPERTIES + publicKey;
    }
}

DataSourceContextHolder

使用ThreadLocal保存当前线程的数据源key name,并实现set、get、clear方法;

public class DataSourceContextHolder {

    private static final ThreadLocal<String> dataSourceKey = new InheritableThreadLocal<>();

    public static void setDataSourceKey(String tenantKey) {
        dataSourceKey.set(tenantKey);
    }

    public static String getDataSourceKey() {
        return dataSourceKey.get();
    }

    public static void clearDataSourceKey() {
        dataSourceKey.remove();
    }
}

DynamicDataSource(重点)

继承AbstractRoutingDataSource

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值