由于每个框架不尽相同,所以以下配置仅供参考。我不喜欢说废话,废话说多了一没用,刚才好像打错了一个字,把一改成也,谢谢,好了,废话不多说,我们开始吧!
需呀配置以下文件:
- jdbc.properties
- springMvc-base.xml
- DataSource.class
- DataSourceAspect.class
- DynamicDataSource.class
- DynamicDataSourceHolder.class
jdbc.properties
#####################
# #
# SqlServer #
# #
#####################
driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
url=jdbc:sqlserver://192.168.5.98:1433;databaseName=\u4f60\u731c\u6211\u7528\u7684\u4ec0\u4e48\u540d\u5b57
username=sa
password=sa
#####################
# #
# Oracle #
# #
#####################
driver_two=oracle.jdbc.driver.OracleDriver
url_two=jdbc:oracle:thin:@192.168.5.99:1521:ORCL
username_two=xxxxxxx
password_two=xxxxxxx
validationQuery_two:select 1 from dual
filters:stat
maxActive:20
initialSize:1
maxWait:60000
minIdle:10
maxIdle:15
timeBetweenEvictionRunsMillis:60000
minEvictableIdleTimeMillis:300000
validationQuery:select 1
testWhileIdle:true
testOnBorrow:false
testOnReturn:false
maxOpenPreparedStatements:20
removeAbandoned:true
removeAbandonedTimeout:1800
logAbandoned:true
springMvc-base.xml
这里只贴核心配置
两个druid 连接池配置
<!-- 配置数据源:阿里 druid数据库连接池 -->
<bean id="dataSource_sqlserver" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<!-- 数据库基本信息配置 -->
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<property name="driverClassName" value="${driver}" />
<property name="filters" value="${filters}" />
<!-- 最大并发连接数 -->
<property name="maxActive" value="${maxActive}" />
<!-- 初始化连接数量 -->
<property name="initialSize" value="${initialSize}" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="${maxWait}" />
<!-- 最小空闲连接数 -->
<property name="minIdle" value="${minIdle}" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" />
<property name="validationQuery" value="${validationQuery}" />
<property name="testWhileIdle" value="${testWhileIdle}" />
<property name="testOnBorrow" value="${testOnBorrow}" />
<property name="testOnReturn" value="${testOnReturn}" />
<property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}" />
<!-- 打开removeAbandoned功能 -->
<property name="removeAbandoned" value="${removeAbandoned}" />
<!-- 1800秒,也就是30分钟 -->
<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="${logAbandoned}" />
</bean>
<bean id="dataSource_oracle" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<!-- 数据库基本信息配置 -->
<property name="url" value="${url_two}" />
<property name="username" value="${username_two}" />
<property name="password" value="${password_two}" />
<property name="driverClassName" value="${driver_two}" />
<property name="filters" value="${filters}" />
<!-- 最大并发连接数 -->
<property name="maxActive" value="${maxActive}" />
<!-- 初始化连接数量 -->
<property name="initialSize" value="${initialSize}" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="${maxWait}" />
<!-- 最小空闲连接数 -->
<property name="minIdle" value="${minIdle}" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" />
<property name="validationQuery" value="${validationQuery_two}" />
<property name="testWhileIdle" value="${testWhileIdle}" />
<property name="testOnBorrow" value="${testOnBorrow}" />
<property name="testOnReturn" value="${testOnReturn}" />
<property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}" />
<!-- 打开removeAbandoned功能 -->
<property name="removeAbandoned" value="${removeAbandoned}" />
<!-- 1800秒,也就是30分钟 -->
<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="${logAbandoned}" />
</bean>
<!--多数据源选择-->
<bean id="dataSource" class="com.googosoft.util.double_datasource.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="dataSource_sqlserver" key="dataSource_sqlserver"></entry>
<entry value-ref="dataSource_oracle" key="dataSource_oracle"></entry>
</map>
</property>
</bean>
<!-- 配置数据库注解aop -->
<!--多数据源选择-->
<bean id="dataSourceAspect" class="com.googosoft.util.double_datasource.DataSourceAspect"/>
这里多数据源选择 有一个aop的顺序,不要配置反了
<aop:config>
<!-- id:事务切入点名称 expression:事务切入点正则表达式 -->
<aop:pointcut id="serviceMethods" expression="execution(* com.bjkjdx.serviceImpl..*.*(..))" />
<!--数据源选择切面,保证在事务开始之前执行-->
<!--<aop:advisor pointcut-ref="serviceMethods" advice-ref="txAdvice" />-->
<!--多数据源选择-->
<aop:advisor pointcut-ref="serviceMethods" advice-ref="dataSourceAspect" order="1" />
<aop:advisor pointcut-ref="serviceMethods" advice-ref="txAdvice" order="2" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 以delete、insert、update、sava、do、go开头的所有方法采用只读型事务控制类型 -->
<tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
<tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
<tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
<tx:method name="save*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
<tx:method name="do*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" timeout="10" />
<tx:method name="go*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" timeout="10" />
<!-- 以load、find、search、select、get开头的所有方法采用只读型事务控制类型 -->
<tx:method name="load*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="search*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
然后是代码:(当然我现在的能力还写不出这么NX的代码,谢谢我曾经抄过的某位码神,实在是忘了抄的谁的了,囧)
DataSource.class
使用注解来动态切换数据源
@Documented
@Retention(RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface DataSource {
String name();
// String name() default DataSource.dataSource_sqlserver;
}
DataSourceAspect.class
监听springmvc框架数据源选择,在事务开始之前,进行数据源切换
这里配置默认的数据源
public class DataSourceAspect implements MethodBeforeAdvice,AfterReturningAdvice
{
/*调用方法
* @DataSource(name= DataSourceAspect.dataSource_oracle)
* */
public static final String dataSource_sqlserver = "dataSource_sqlserver";
public static final String dataSource_oracle = "dataSource_oracle";
@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
DynamicDataSourceHolder.clearDataSourceType();
}
@Override
public void before(Method method, Object[] args, Object target)
throws Throwable {
//首先取类上的数据源
if(method.getDeclaringClass().isAnnotationPresent(DataSource.class) && !method.isAnnotationPresent(DataSource.class)) {
DataSource datasource = method.getDeclaringClass().getAnnotation(DataSource.class);
DynamicDataSourceHolder.setDataSourceType(());
//方法上的数据源 优先级高于类上的
} else if (method.isAnnotationPresent(DataSource.class)) {
DataSource datasource = method.getAnnotation(DataSource.class);
DynamicDataSourceHolder.setDataSourceType(());
}
else
{
DynamicDataSourceHolder.setDataSourceType(dataSource_sqlserver);
}
}
}
DynamicDataSource.class
动态数据源类
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
String dataSource =DynamicDataSourceHolder.getDataSourceType();
return dataSource;
}
}
DynamicDataSourceHolder.class
获得和设置上下文环境的类,主要负责改变上下文数据源的名称
public class DynamicDataSourceHolder {
private static final ThreadLocal<String> contextHolder= new ThreadLocal<String>();
public static void setDataSourceType(String dataSourceType) {
contextHolder.set(dataSourceType);
}
public static String getDataSourceType() {
return contextHolder.get();
}
public static void clearDataSourceType() {
contextHolder.remove();
}
}
使用方法:
在你的service层事务开始的地方,即事务开始之前,使用如下代码切换数据源:
@DataSource(name= DataSourceAspect.dataSource_oracle)
这样就可以实现数据源切换了