AbstractRoutingDataSource 實現切換資料來源的原理
檢視這個類可以發現。它繼承了DataSource,那麼找到他的getConnection方法
public Connection getConnection() throws SQLException {
return this.determineTargetDataSource().getConnection();
複製程式碼
}
protected DataSource determineTargetDataSource() {
Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
Object lookupKey = this.determineCurrentLookupKey();
DataSource dataSource = (DataSource)this.resolvedDataSources.get(lookupKey);
if(dataSource == null && (this.lenientFallback || lookupKey == null)) {
dataSource = this.resolvedDefaultDataSource;
}
if(dataSource == null) {
throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
} else {
return dataSource;
}
複製程式碼
}
可以看出關鍵程式碼determineTargetDataSource中,這裡處理了資料來源切換,那麼只需要寫一個子類,將determineCurrentLookupKey這個方法重寫下,即可做到資料來源切換。
資料來源配置
用到的部分程式碼如下,其餘的用專案中的即可:
-資料庫配置檔案
#------------main MySQL ------------
hibernate.dialect=org.hibernate.dialect.MySQLDialect
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://47.94.18.202:3306/jxncpshop?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root
#------------main MySQL2 ------------
#openData.hibernate.dialect=org.hibernate.dialect.MySQLDialect
openData.jdbc.driver=com.mysql.jdbc.Driver
openData.jdbc.url=jdbc:mysql://47.94.18.202:3306/jnncpshop?useUnicode=true&characterEncoding=UTF-8
openData.jdbc.username=root
openData.jdbc.password=root
url1=http://www.jnncpshop.com:8081/
url2=http://www.jxncpshop.com:8081/
applicationContext.xml的配置
此處程式碼中需要主義的地方有:dataSource配置的key要和後面修改資料庫是的名稱保持一致,
-切換資料來源和事務管理的先後順序:這裡通過order 來設定優先順序,保證切換資料來源的切面在事務管理之前
-sessionFactory配置注意的地方的地方:將預設的資料庫配置取消,不然會無法切換
1:動態選擇資料來源 方法類
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
- Created by Administrator on 2019/1/16.
*/
public class ChooseDataSourceextends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
複製程式碼
String dataSource = HandleDataSource.getDataSource();
HandleDataSource.clearDataSource();//每次設定完清除,保證獲取預設資料庫
return dataSource;
複製程式碼
}
}
2:資料來源切換類
package com.ewebtd.eshop.admin.common;
/**
- Created by Administrator on 2019/1/16.
*/
public class HandleDataSource {
// 資料來源名稱執行緒池,ThreadLocal是執行緒安全的,並且不能在多執行緒之間共享
public static final ThreadLocalholder =new ThreadLocal();
複製程式碼
public static void setDataSource(String dataSource){
holder.set(dataSource);
}
public static String getDataSource(){
return ((String)holder.get());
}
public static void clearDataSource() {
holder.remove();
}
}
3.資料來源名稱配置類
/**
-
資料來源配置名稱--與配置檔案中的key同名
-
Created by Administrator on 2019/1/16.
*/
public class DataSourceConst {
public static final StringDEFAULT ="default";
public static final StringSITE_MAIN ="siteMain";
}
4.自定義Filter實現根據域名去在每次請求前判斷要選擇的資料來源
import com.ewebtd.eshop.admin.common.DataSourceConst;
import com.ewebtd.eshop.admin.common.HandleDataSource;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
/**
- Created by Administrator on 2019/1/16.
*/
public class ChooseDataSourceFilterimplements Filter{
@Override
public void init(FilterConfig filterConfig)throws ServletException {
複製程式碼
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {
複製程式碼
if (!(servletRequestinstanceof HttpServletRequest) || !(servletResponseinstanceof HttpServletResponse)) {
throw new ServletException("OncePerRequestFilter just supports HTTP requests");
}
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
StringBuffer url = httpRequest.getRequestURL();
String tempContextUrl = url.delete(url.length() - httpRequest.getRequestURI().length(), url.length()).append("/").toString();
Properties properties =new Properties();
BufferedReader bufferedReader =new BufferedReader(new FileReader("E:/1227/source/trunk/eshop/eshopadmin/src/main/java/com/ewebtd/eshop/config/db.properties"));
properties.load(bufferedReader);
// if(tempContextUrl.equals("www.jnncpshop.com:8081/")){
if(tempContextUrl.equals(properties.getProperty("url1"))){
複製程式碼
HandleDataSource.setDataSource(DataSourceConst.SITE_MAIN);
}else if(tempContextUrl.equals(properties.getProperty("url2"))){
HandleDataSource.setDataSource(DataSourceConst.DEFAULT);
}
filterChain.doFilter(servletRequest, servletResponse);
return;
}
@Override
public void destroy() {
複製程式碼
}
}
5.在web.xml中配置一下,過濾所有請求,注意在過濾器執行鏈的順序
ChooseDataSourceFilter
com.ewebtd.eshop.admin.filter.ChooseDataSourceFilter
ChooseDataSourceFilter
/*
測試的話需要修改本機hosts檔案,對127.0.0.1做域名對映,然後重啟電腦
啟動tomcat,效果如圖: