这个版本是看了网上很多版本整合而来
需要的多数据源操作类
/**
* 数据源设置类
* @author admin
*
*/
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setDbType(String dbType) {
contextHolder.set(dbType);
}
public static String getDbType() {
return ((String) contextHolder.get());
}
public static void clearDbType() {
contextHolder.remove();
}
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSourceKey {
String value() default "";
}
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDbType();
}
}
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
/**
* 该方法为切面方法,保证我们在执行数据库操作前可以动态的切换数据源
*
* Created by lxh5316 on 2016/6/15.
*/
@Component
@Aspect
public class MultipleDataSourceAspectAdvice {
private Logger logger = LogManager.getLogger(MultipleDataSourceAspectAdvice.class);
/**
* 可以在执行方法之前和之后改变参数和返回值
* @param joinPoint用于获取目标方法相关信息的参数
* @return 最终的返回值
* @throws Throwable
*/
@Around("execution(* com.coffee.dao.*.*(..))")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
logger.debug("--multiple data source aop--");
Object object = joinPoint.getTarget();
logger.debug("Target Class:"+object.getClass());
DataSourceKey annotation = AnnotationUtils.findAnnotation(object.getClass(),DataSourceKey.class);
if (null!=annotation){
String value = annotation.value();
if(null!=value&&value.length()>0){
DataSourceContextHolder.setDbType(value);
logger.debug("Data Source Key :"+value);
}
}else {//没有注解时设置dbtype为null,表示用默认值
DataSourceContextHolder.setDbType(null);
}
return joinPoint.proceed();
}
}
配置文件:
application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<import resource="applicationContext-mybatis.xml"/>
<import resource="application-transaction.xml"/>
<!-- 使用spring自带的占位符替换功能 -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!-- 允许JVM参数覆盖 -->
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<!-- 忽略没有找到的资源文件 -->
<property name="ignoreResourceNotFound" value="true" />
<!-- 配置资源文件 -->
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<context:component-scan base-package="com.coffee" />
<!-- 数据库连接池 :coffeeHubDataSource -->
<bean id="coffeeHubDataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<!-- 数据库驱动 -->
<property name="driverClassName" value="${coffeeHub.jdbc.driver}" />
<!-- 相应驱动的jdbcUrl -->
<property name="url" value="${coffeeHub.jdbc.url}" />
<!-- 数据库的用户名 -->
<property name="username" value="${coffeeHub.jdbc.username}" />
<!-- 数据库的密码 -->
<property name="password" value="${coffeeHub.jdbc.password}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="40"></property>
<!-- 连接池最大数量 -->
<property name="maxActive" value="40"></property>
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="10"></property>
<!-- 连接池最小空闲 -->
<property name="minIdle" value="1"></property>
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000"></property>
</bean>
<!-- 数据库连接池 :appServerDataSource -->
<bean id="appserverDataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<!-- 数据库驱动 -->
<property name="driverClassName" value="${appserver.jdbc.driver}" />
<!-- 相应驱动的jdbcUrl -->
<property name="url" value="${appserver.jdbc.url}" />
<!-- 数据库的用户名 -->
<property name="username" value="${appserver.jdbc.username}" />
<!-- 数据库的密码 -->
<property name="password" value="${appserver.jdbc.password}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="40"></property>
<!-- 连接池最大数量 -->
<property name="maxActive" value="40"></property>
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="10"></property>
<!-- 连接池最小空闲 -->
<property name="minIdle" value="1"></property>
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000"></property>
</bean>
<!-- 数据库连接池 -->
<bean id="dynamicDataSource" class="com.coffee.sys.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="coffeeHubDataSource" key="coffeeHubDataSource" />
<entry value-ref="appserverDataSource" key="appserverDataSource" />
</map>
</property>
<!-- 默认使用appserverDataSource的数据源 -->
<property name="defaultTargetDataSource" ref="coffeeHubDataSource" />
</bean>
</beans>
application-transaction.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!-- 定义事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 使用动态的数据源dynamicDataSource -->
<property name="dataSource" ref="dynamicDataSource" />
</bean>
<!-- 定义事务策略 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--所有以query开头的方法都是只读的 -->
<tx:method name="query*" read-only="true" />
<!--其他方法使用默认事务策略 -->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!--pointcut元素定义一个切入点,execution中的第一个星号 用以匹配方法的返回类型, 这里星号表明匹配所有返回类型。 com.abc.dao.*.*(..)表明匹配cn.millery.mybatis.service包下的所有类的所有
方法 -->
<!-- 设置切面编程 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
</beans>
applicatioinContext-mybatis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 定义Mybatis的SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 定义数据源,数据源使用动态的数据源dynamicDataSource -->
<property name="dataSource" ref="dynamicDataSource" />
<!-- 指定mybatis全局配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml" />
<!-- 扫描mapper目录以及子目录下的所有xml文件 -->
<property name="mapperLocations" value="classpath:mapper/*.xml" />
<!-- 别名扫描包 -->
<!-- <property name="typeAliasesPackage" value="com.coffee" /> -->
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.coffee.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- <property name="annotationClass" value="org.springframework.stereotype.Repository"/> -->
</bean>
</beans>
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 开启驼峰自动映射 -->
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
</configuration>
jdbc.properties
#db1 db1.jdbc.driver=com.mysql.jdbc.Driver db1.jdbc.url=jdbc:mysql://127.0.0.1:3306/db1?useUnicode=true&characterEncoding=utf8 db1.jdbc.username=root db1.jdbc.password=123456 #db2 db2.jdbc.driver=com.mysql.jdbc.Driver db2.jdbc.url=jdbc:mysql://127.0.0.1:3306/db2?useUnicode=true&characterEncoding=utf8 db2.jdbc.username=root db2.jdbc.password=123456
测试类:
核心是在dao类上加上注解即可
import org.springframework.stereotype.Repository; import com.coffee.bean.AccessRuleBean; import com.coffee.constant.Constants; import com.coffee.sys.DataSourceKey; /** * * @author admin * */ @Repository @DataSourceKey(value=Constants.APP_SERVER_DATA_SOURCE) public interface AccessRuleDao { AccessRuleBean getAccessRule(); }
其余业务代码忽略,自行书写
测试代码:
/** * 多数据源测试类 * @author admin * */ public class MutiDataSourceTest { /** * @param args */ public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("application-context.xml"); System.out.println("start ..."); ContractService cs = (ContractService)ac.getBean("contractService"); ContractBean contract = cs.getContract(); System.out.println(contract.getBorrowerName()); System.out.println("end ..."); AccessRuleService accessRuleService = (AccessRuleService)ac.getBean("accessRuleService"); // DataSourceContextHolder.setDbType("appserverDataSource"); AccessRuleBean accessRule = accessRuleService.getAccessRule(); String serialno = accessRule.getSerialno(); System.out.println("serialno:" + serialno); System.out.println("end ..."); contract = cs.getContract(); System.out.println(contract.getBorrowerName()); }