笔者主要从事c#开发,近期因为项目需要,搭建了一套spring-cloud微服务框架,集成了eureka服务注册中心、
gateway网关过滤、admin服务监控、auth授权体系验证,集成了redis、swagger、jwt、mybatis多数据源等各项功能。
具体搭建过程后续另写播客介绍。具体结构如下:
在搭建过程集成mybatis的时候,考虑到单一数据源无法满足实际业务需要,故结合c#的开发经验,进行多数据源动态集成。
mybatis的多数据源可以采用两种方式进行,第一种是分包方式实现,这种方式灵活性不高,而且较为繁琐,故不做过多介绍。
另一种方式是采用AOP的思想,进行注解动态切换,参考网上教程,核心思想是依靠 继承AbstractRoutingDataSource,重写determineCurrentLookupKey()方法,在该方法中使用DatabaseContextHolder获取当前线程的dataSource。
但是网上方法大都是首先定义好各个datasource,比如有三个数据源,就需要实现定义好三个datasource,笔者感觉这种方法,在我目前这套框架中不够灵活,因为笔者采用的是微服务框架,考虑到各个服务都有可能使用不同的数据源,而多数据源动态切换是放在公共方法中实现的,如果每有新的数据源就要定义一个,对代码的侵入性太高,在c#中,选择数据源很容易,根据连接名称就可以切换过去,如下所示:
<connectionStrings> <add name="test1" connectionString="server=127.0.0.1;user id=root;password=123456;database=db1;charset=utf8" providerName="MySql.Data.MySqlClient" /> <add name="test2" co<p style="color:transparent">本文来源gao!daima.com搞$代!码网</p>nnectionString="server=127.0.0.1;user id=root;password=123456;database=db2;charset=utf8" providerName="MySql.Data.MySqlClient" /> <add name="test3" connectionString="server=127.0.0.1;user id=root;password=123456;database=db3;charset=utf8" providerName="MySql.Data.MySqlClient" /> <connectionStrings>
能不能像c#这样根据连接名称就自动选择呢,笔者的连接配置如下所示:
spring: application: name: csg-auth datasource: kbase: - driverClassName: com.kbase.jdbc.Driver jdbcUrl: jdbc:kbase://127.0.0.1 username: DBOWN password: jdbc: - driverClassName: com.mysql.cj.jdbc.Driver jdbcUrl: jdbc:mysql://localhost:3306/nacos?serverTimezone=GMT%2B8&useUnicode=false&characterEncoding=utf8&useSSL=false username: root password: 123456 connName: nacos - driverClassName: com.mysql.cj.jdbc.Driver jdbcUrl: jdbc:mysql://localhost:3306/tpi?serverTimezone=GMT%2B8&useUnicode=false&characterEncoding=utf8&useSSL=false username: root password: 123456 connName: tpi
其中kbase不用理会,是我们公司自己的数据库,jdbc是维护的连接集合,其中connName就是我们自定义的连接名称,
根据connName就可以自动切换到对应数据源。
笔者实现代码如下:
第一步
首先,编写DynamicDataSource类集成AbstractRoutingDataSource,重写determineCurrentLookupKey方法,该方法主要作用是选择数据源的key
代码如下:
/** * 动态数据源 * */ public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceHolder.getDataSource(); } }