多租戶情況下數據源的設置(AbstractRoutingDataSource)

在多租戶的情況,如果將所有租戶的數據保存在同一數據庫同一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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章