SpringMvc 4.3 多数据源示例
来源:互联网 发布:2016团购份额CDICC数据 编辑:程序博客网 时间:2024/06/16 00:36
由于每个框架不尽相同,所以以下配置仅供参考。我不喜欢说废话,废话说多了一没用,刚才好像打错了一个字,把一改成也,谢谢,好了,废话不多说,我们开始吧!
需呀配置以下文件:
- jdbc.properties
- springMvc-base.xml
- DataSource.class
- DataSourceAspect.class
- DynamicDataSource.class
- DynamicDataSourceHolder.class
jdbc.properties
###################### ## SqlServer ## ######################driver=com.microsoft.sqlserver.jdbc.SQLServerDriverurl=jdbc:sqlserver://192.168.5.98:1433;databaseName=\u4f60\u731c\u6211\u7528\u7684\u4ec0\u4e48\u540d\u5b57username=sapassword=sa###################### ## Oracle ## ######################driver_two=oracle.jdbc.driver.OracleDriverurl_two=jdbc:oracle:thin:@192.168.5.99:1521:ORCLusername_two=xxxxxxxpassword_two=xxxxxxxvalidationQuery_two:select 1 from dualfilters:statmaxActive:20initialSize:1maxWait:60000minIdle:10maxIdle:15timeBetweenEvictionRunsMillis:60000minEvictableIdleTimeMillis:300000validationQuery:select 1testWhileIdle:truetestOnBorrow:falsetestOnReturn:falsemaxOpenPreparedStatements:20removeAbandoned:trueremoveAbandonedTimeout:1800logAbandoned: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(datasource.name()); //方法上的数据源 优先级高于类上的 } else if (method.isAnnotationPresent(DataSource.class)) { DataSource datasource = method.getAnnotation(DataSource.class); DynamicDataSourceHolder.setDataSourceType(datasource.name()); } 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)
这样就可以实现数据源切换了
阅读全文