AbstractRoutingDataSource 實現切換數據源的原理java
查看這個類能夠發現。它繼承了DataSource,那麼找到他的getConnection方法mysql
public Connection getConnection() throws SQLException {web
return this.determineTargetDataSource().getConnection();
複製代碼
}spring
protected DataSource determineTargetDataSource() {sql
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這個方法重寫下,便可作到數據源切換。tomcat
數據源配置安全
用到的部分代碼以下,其他的用項目中的便可:session
-數據庫配置文件多線程
#------------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;
/**
*/
public class ChooseDataSourceextends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
複製代碼
String dataSource = HandleDataSource.getDataSource();
HandleDataSource.clearDataSource();//每次設置完清除,保證獲取默認數據庫
return dataSource;
複製代碼
}
}
2:數據源切換類
package com.ewebtd.eshop.admin.common;
/**
*/
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;
/**
*/
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,效果如圖: