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,效果如图: