基于spring的動(dòng)態(tài)數(shù)據(jù)源
項(xiàng)目過程中遇到這樣一個(gè)需求,系統(tǒng)啟動(dòng)后動(dòng)態(tài)設(shè)置數(shù)據(jù)源,不同用戶登錄系統(tǒng)后訪問的數(shù)據(jù)庫不同。
好在所有書庫結(jié)構(gòu)一致。
用spring 的AbstractRoutingDataSource解決了這個(gè)問題。
原理如圖:

項(xiàng)目采用的是hibernate,直接在spring.xml設(shè)置sessionFactory的dataSource屬性為動(dòng)態(tài)數(shù)據(jù)源即可。
因?yàn)轫?xiàng)目所有數(shù)據(jù)庫結(jié)構(gòu)都一致,為了避免每次設(shè)置數(shù)據(jù)源的時(shí)候要改一堆參數(shù),修改了spring AbstractRoutingDataSource類增加了一個(gè)getTargetDataSources方法,獲取當(dāng)前數(shù)據(jù)源詳細(xì)信息,在其基礎(chǔ)上修改數(shù)據(jù)庫名稱、用戶名、密碼即可,不用每次設(shè)置一堆參數(shù)。
Map<String,ComboPooledDataSource> targetDataSources=dynamicDataSource.getTargetDataSources();

if(targetDataSources==null)
{
targetDataSources=new HashMap<String, ComboPooledDataSource>();
targetDataSources.put("baseDataSource", baseDataSource);
}
targetDataSources.put(dataSourceName, subSystemDataSource);
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.afterPropertiesSet();另外,設(shè)置AbstractRoutingDataSource參數(shù)后要調(diào)用afterPropertiesSet()方法,spring容器才會(huì)進(jìn)行加載操作。
在動(dòng)態(tài)設(shè)置數(shù)據(jù)源方面,可以通過兩種方式實(shí)現(xiàn):
1.在action(項(xiàng)目使用struts)中進(jìn)行設(shè)置,可以確保在每個(gè)servlet線程中數(shù)據(jù)源是一致的。
2.以aop方式,對(duì)service方法進(jìn)行攔截,根據(jù)需求設(shè)置不同數(shù)據(jù)源。