多租户情况下数据源的设置(AbstractRoutingDataSource)

来源:互联网 发布:fuse linux命令 编辑:程序博客网 时间:2024/05/17 08:54

在多租户的情况,如果将所有租户的数据保存在同一数据库同一schama内,这会给数据的管理和安全带来很大风险,虽然这样做的成本最佳。

另一种方式是将不同的租户保存在不同的schama内,这样一个租户对应一个schema,这样管理比较方便,出现问题风险也比较小点,实现这样的方式就会有多个数据源,

因为所有的租户对就的都一同一个应用实体,它们只是应用不同的数据库。所以我们就要在每个用户在操作应用系统时,为这个用户设置正确的数据源来对数据库进行操作,

spring 为我们提供了数据源路由的抽象类,AbstractRoutingDataSource。继承这个抽象类为,首先初始化所有租户的数据源,然后对过protected Object determineCurrentLookupKey() 方法返回当前租户的数据源。达到对数据库的操作。

下面简单说明下AbstractRoutingDataSource类:

首先看下AbstractRoutingDataSource类结构,继承了AbstractDataSource

Java代码  收藏代码
  1. public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {  
  2.   
  3. }  
 

既然是AbstractDataSource,当然就是javax.sql.DataSource的子类,于是我们自然地回去看它的getConnection方法:

Java代码  收藏代码
  1. public Connection getConnection() throws SQLException {  
  2.     return determineTargetDataSource().getConnection();  
  3. }  

 原来奥妙就在determineTargetDataSource()里:

Java代码  收藏代码
  1. /** 
  2.  * Retrieve the current target DataSource. Determines the 
  3.  * {@link #determineCurrentLookupKey() current lookup key}, performs 
  4.  * a lookup in the {@link #setTargetDataSources targetDataSources} map, 
  5.  * falls back to the specified 
  6.  * {@link #setDefaultTargetDataSource default target DataSource} if necessary. 
  7.  * @see #determineCurrentLookupKey() 
  8.  */  
  9. protected DataSource determineTargetDataSource() {  
  10.     Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");  
  11.     Object lookupKey = determineCurrentLookupKey();  
  12.     DataSource dataSource = (DataSource) this.resolvedDataSources.get(lookupKey);  
  13.     if (dataSource == null) {  
  14.         dataSource = this.resolvedDefaultDataSource;  
  15.     }  
  16.     if (dataSource == null) {  
  17.         throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");  
  18.     }  
  19.     return dataSource;  
  20. }  

这里用到了我们需要进行实现的抽象方法determineCurrentLookupKey(),该方法返回需要使用的DataSource的key值,然后根据这个key从resolvedDataSources这个map里取出对应的DataSource,如果找不到,则用默认的resolvedDefaultDataSource

 

Java代码  收藏代码
  1. <bean id="onlineDynamicDataSource" class="com.xx.stat.base.dynamic.DynamicDataSource">  
  2.    <property name="targetDataSources">     
  3.       <map key-type="java.lang.String">     
  4.          <entry key="xx" value-ref="dataSourceXX"/>     
  5.          <entry key="yy" value-ref="dataSourceYY"/>     
  6.       </map>     
  7.    </property>     
  8.    <property name="defaultTargetDataSource" ref="dataSource"/>    
  9. </bean>  
 

观察上面的配置文件,发现我们配置的是targetDataSources和defaultTargetDataSource


原创粉丝点击