1 编写DataSourceHolder
public class DataSourceHolder {
private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();
/**
* 获取当前线程的数据源路由的key
*/
public static String getKey() {
return threadLocal.get();
}
/**
* 绑定当前线程数据源路由的key
* 使用完成后必须调用removeRouteKey()方法删除
*/
public static void setKey(String key) {
threadLocal.set(key);
}
/**
* 删除与当前线程绑定的数据源路由的key
*/
public static void removeKey() {
threadLocal.remove();
}
}
2 编写MultipleDataSource实现AbstractRoutingDataSource
public class MultipleDataSource extends AbstractRoutingDataSource {
//通过这个值切换数据源
@Override
protected Object determineCurrentLookupKey() {
return DataSourceHolder.getKey();
}
}
3 编写注解 @DataSourceKey
@Target({ElementType.METHOD})
@Retention(RUNTIME)
public @interface DataSourceKey {
//要切换的数据源,
String value();
}
4 编写aop DataSourceAspect拦截注解
@Aspect
@Component
public class DataSourceAspect {
private final Log logger = LogFactory.getLog(this.getClass());
@Around("@annotation(changeDataSource)")
public Object aroundAdvice(ProceedingJoinPoint point, DataSourceKey changeDataSource) throws Throwable {
try {
//方法执行前修改数据源
DataSourceHolder.setKey(changeDataSource.value());
return point.proceed();
} catch (Exception e) {
logger.error(e.getMessage());
} finally {
//方法执行后切换到默认数据源
DataSourceHolder.removeKey();
}
return null;
}
}
5 编写xml
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="1"/>
<property name="minIdle" value="1"/>
<property name="maxActive" value="300"/>
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000"/>
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000"/>
<property name="validationQuery" value="SELECT 'x' FROM DUAl"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="true"/>
<property name="maxPoolPreparedStatementPerConnectionSize" value="20"/>
<!-- 配置监控统计拦截的filters,去掉后监控界面sql无法统计 -->
<property name="filters" value="stat"/>
</bean>
<bean id="demo" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}"/>
<property name="username" value="goisan_gemini"/>
<property name="password" value="gemini"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="1"/>
<property name="minIdle" value="1"/>
<property name="maxActive" value="300"/>
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000"/>
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000"/>
<property name="validationQuery" value="SELECT 'x' FROM DUAl"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="true"/>
<property name="maxPoolPreparedStatementPerConnectionSize" value="20"/>
<!-- 配置监控统计拦截的filters,去掉后监控界面sql无法统计 -->
<property name="filters" value="stat"/>
</bean>
<bean id="multipleDataSource" class="com.goisan.sdcenter.dynamicdatasource.MultipleDataSource" lazy-init="true">
<property name="targetDataSources">
<map key-type="java.lang.String">
<!-- key数据源名称,通过key来实现切换数据源 -->
<entry key="dataSource" value-ref="dataSource"/>
<entry key="demo" value-ref="demo"/>
</map>
</property>
<!-- 默认数据源 -->
<property name="defaultTargetDataSource" ref="dataSource"/>
</bean>