首先在spring下配置多个dataSourcejava
<bean id="masterDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${master.driverClass}" /> <property name="jdbcUrl" value="${master.jdbcUrl}" /> <property name="user" value="${master.user}" /> <property name="password" value="${master.password}" /> <property name="minPoolSize" value="${master.minPoolSize}"></property> <property name="maxPoolSize" value="${master.maxPoolSize}"></property> <property name="maxIdleTime" value="${master.maxIdleTime}"></property> <property name="acquireIncrement" value="${master.acquireIncrement}"></property> <property name="maxStatements" value="${master.maxStatements}"></property> <property name="initialPoolSize" value="${master.initialPoolSize}"></property> <property name="idleConnectionTestPeriod" value="${master.idleConnectionTestPeriod}"></property> <property name="acquireRetryAttempts" value="${master.acquireRetryAttempts}"></property> <property name="breakAfterAcquireFailure" value="${master.breakAfterAcquireFailure}"></property> <property name="testConnectionOnCheckout" value="${master.testConnectionOnCheckout}"></property> <property name="autoCommitOnClose" value="${master.autoCommitOnClose}"></property> </bean> <bean id="slaveDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${slave.driverClass}" /> <property name="jdbcUrl" value="${slave.jdbcUrl}" /> <property name="user" value="${slave.user}" /> <property name="password" value="${slave.password}" /> <property name="minPoolSize" value="${slave.minPoolSize}"></property> <property name="maxPoolSize" value="${slave.maxPoolSize}"></property> <property name="maxIdleTime" value="${slave.maxIdleTime}"></property> <property name="acquireIncrement" value="${slave.acquireIncrement}"></property> <property name="maxStatements" value="${slave.maxStatements}"></property> <property name="initialPoolSize" value="${slave.initialPoolSize}"></property> <property name="idleConnectionTestPeriod" value="${slave.idleConnectionTestPeriod}"></property> <property name="acquireRetryAttempts" value="${slave.acquireRetryAttempts}"></property> <property name="breakAfterAcquireFailure" value="${slave.breakAfterAcquireFailure}"></property> <property name="testConnectionOnCheckout" value="${slave.testConnectionOnCheckout}"></property> <property name="autoCommitOnClose" value="${slave.autoCommitOnClose}"></property> </bean>
以后自定义一个数据源 算法
<bean id="myDynamicDataSource" class="com.up366.lsp.db.datasource.DynamicDataSource"> <property name="targetDataSources"> <!-- 标识符类型 --> <map key-type="java.lang.String"> <entry key="master" value-ref="masterDataSource"/> <entry key="slave" value-ref="slaveDataSource" /> </map> </property> <property name="defaultTargetDataSource" ref="masterDataSource" /> </bean>
本身写的自定义数据源 spring
package com.up366.lsp.db.datasource; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceHolder.getDataSouce(); } }
以后用线程变量控制sql
package com.up366.lsp.db.datasource; public class DynamicDataSourceHolder { public static final ThreadLocal<String> holder = new ThreadLocal<String>(); public static void setDataSource(String name) { holder.set(name); } public static String getDataSouce() { return holder.get(); } public static void clearDataSouce() { holder.remove(); } public static void setMaster() { DynamicDataSourceHolder.clearDataSouce(); } public static void setSlave() { DynamicDataSourceHolder.setDataSource("slave"); } }
以后配置一个执行前的aop 动态加载数据源express
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> <bean id="manyDataSourceAspect" class="com.up366.lsp.db.datasource.DataSourceAspect" /> <aop:config> <aop:aspect id="c" ref="manyDataSourceAspect"> <aop:pointcut id="tx" expression="execution(* com.up366.lsp.db.dao.*.*(..))"/> <aop:before pointcut-ref="tx" method="before"/> </aop:aspect> </aop:config>
package com.up366.lsp.db.datasource; import java.lang.reflect.Method; import org.apache.ibatis.mapping.SqlCommandType; import org.apache.ibatis.session.SqlSessionFactory; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.annotation.Autowired; import com.up366.lsp.db.datasource.anno.Master; import com.up366.lsp.db.datasource.anno.Slave; public class DataSourceAspect { @Autowired private SqlSessionFactoryBean sqlSessionFactory; public void before(JoinPoint point) { Object target = point.getTarget(); String method = point.getSignature().getName(); Class<?>[] classz = target.getClass().getInterfaces(); Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()) .getMethod().getParameterTypes(); try { Method m = classz[0].getMethod(method, parameterTypes); if (m != null ) { if(m.isAnnotationPresent(Slave.class)){ DynamicDataSourceHolder.setSlave(); return ; } if(m.isAnnotationPresent(Master.class)){ DynamicDataSourceHolder.setMaster(); return ; } //在没有配置的状况下走默认 String key = classz[0].getName()+"." + m.getName(); SqlSessionFactory ss = sqlSessionFactory.getObject(); //获取类型 SqlCommandType type = ss.getConfiguration().getMappedStatement(key,false).getSqlCommandType(); //查询默认从库 if(SqlCommandType.SELECT == type){ DynamicDataSourceHolder.setSlave(); return ; } //增删改默认主库 if(type == SqlCommandType.DELETE || SqlCommandType.INSERT == type || SqlCommandType.UPDATE == type) DynamicDataSourceHolder.setMaster(); } } catch (Exception e) { } } }
基本上完成了 apache
若是是负载均衡的话 能够对从库进行负载多个配置 用算法去肯定session