1.配置 jdbc.properties
配置2个数据源,一个orcale一个mysql为例
#oracle
jdbc.oracle.driver=oracle.jdbc.OracleDriver
jdbc.oracle.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.oracle.user=root
jdbc.oracle.password=root
#mysql
jdbc.mysql.driver=com.mysql.jdbc.Driver
jdbc.mysql.url=jdbc:mysql://127.0.0.1:3306/test2
jdbc.mysql.user=root
jdbc.mysql.password=root
2.在spring的xml文件中加载 jdbc.properties
<!-- 引入属性文件 resource是我自己加的一层目录,问价放哪里你开心就好 -->
<context:property-placeholder location="classpath:resource/*.properties" />
**2.在spring的xml文件中使用druid数据库连接池配置数据源**
<!-- oracle库连接池 -->
<bean id="orcleDataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password driverClassName -->
<property name="driverClassName" value="${jdbc.oracle.driver}" />
<property name="url" value="${jdbc.oracle.url}" />
<property name="username" value="${jdbc.oracle.user}" />
<property name="password" value="${jdbc.oracle.password}" />
</bean>
<!-- mysql库连接池 -->
<bean id="mysqlDataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password driverClassName -->
<property name="driverClassName" value="${jdbc.mysql.driver}" />
<property name="url" value="${jdbc.mysql.url}" />
<property name="username" value="${jdbc.mysql.user}" />
<property name="password" value="${jdbc.mysql.password}" />
</bean>
<!-- 配置数据库切换类 -->
<bean id="dataSource" class="com.test.common.datasource.DynamicDataSource">
<property name="targetDataSources">
<map>
<entry key="orcleDataSource" value-ref="orcleDataSource"/>
<entry key="mysqlDataSource" value-ref="mysqlDataSource"></entry>
</map>
</property>
<!-- 设置默认数据源 -->
<property name="defaultTargetDataSource" ref="orcleDataSource"/>
</bean>
<!-- 配置SqlSessionFactory -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 配置数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描mappers.xml文件 -->
<property name="mapperLocations" value="classpath:com/test/common/mapper/*.xml"></property>
<!-- 加载MyBatis配置文件 -->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
</bean>
<!-- 配置Mapper扫描 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- Mapper扫描包 -->
<property name="basePackage" value="com.test.common.dao.*.dao" />
</bean>
3.动态数据源切换类
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
return DataSourceHolder.getDataSourceType();
}
}
4.使用ThreadLocal安全线程返回数据源名称
public class DataSourceHolder {
/**
* oracle库数据源
*/
public static final String ORACLE_DATA_SOURCE ="oracleDataSource";
/**
* mysql库数据源
*/
public static final String MYSQL_DATA_SOURCE ="mysqlDataSource";
//用ThreadLocal来设置当前线程使用哪个dataSource
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();
}
/**
* 切换数据源
*/
public static void changeCurrentDataSource(String dataSourceType) {
clearDataSourceType();
setDataSourceType(dataSourceType);
}
/**
* 切换回默认数据源
*/
public static void change2DefaulDataSource() {
clearDataSourceType();
}
5.测试
//控制层
@Controller
@RequestMapping("/test")
public class TestlController {
@Autowired
TestService testService;
// 测试数据源切换
@RequestMapping(value="changDataSource" ,method=RequestMethod.GET)
@ResponseBody
public String changeDataSource(String userCode,String type) {//type代表数据源类型
return testService.findUserByUserCode(userCode,type);
}
}
//接口
public interface TestService {
/**
* 测试数据库连接
*/
TestQueryDTO findUserByUserCode(String userCode);
}
//实现类
@Service("testService")
public class TestServiceImpl implements TestService {
@Override
public TestQueryDTO findUserByUserCode(String userCode, String type) {
TestQueryDTO dto=null;
if("2".equals(type)) {//如果type是2就用mysql数据库,其他值都是使用默认的数据库,
DataSourceHolder.changeCurrentDataSource(DataSourceHolder.MYSQL_DATA_SOURCE);
dto=testDao.findUserByUserCode(userCode);
DataSourceHolder.change2DefaulDataSource();
}else{
dto=testDao.findUserByUserCode(userCode);
}
return dto;
}
}
dao层就不写了,到这里就可以动态的切换数据库源了
6.使用注解的方式动态切换数据源
6.1保证aop的jar已经引入
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.1.RELEASE</version>
</dependency>
<!-- aop Spring AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.5</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
6.2在spring的xml中添加切面的配置
<!-- 用来自动将所有被Aspect标注修饰的类 生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
6.3自定义注解
// 切换当前线程的数据源
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomDataSource {
String value();
}
6.4配置aspect的类对有@CustomDataSource 注解标注的方法或类进行切面处理
@Aspect
@Component
public class DataSourceAspect {
//对service的所有方法进行拦截
@Pointcut("execution(* com.test.common.service.impl.*.*(..))")
public void pointerCut() {
}
@Before("pointerCut()")
public void switchDataSource(JoinPoint pjp) throws Throwable{
Signature signature =pjp.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
Method targetMethod=methodSignature.getMethod();
Method realMethod = pjp.getTarget().getClass().getDeclaredMethod(signature.getName(), targetMethod.getParameterTypes());
//首先判断方法级别
CustomDataSource cds=realMethod.getAnnotation(CustomDataSource.class);
if(cds==null){ //判断类级别
cds= AnnotationUtils.findAnnotation(realMethod.getDeclaringClass(), CustomDataSource.class);
}
if(cds==null){ //默认库不需要进行更换
return;
}
String dataSourceName=cds.value(); //获取注解的值
if(dataSourceName!=null&&!dataSourceName.equals("")) //通过数据源路由类切换数据源
DataSourceHolder.changeCurrentDataSource(dataSourceName);
}
@After("pointerCut()")
public void change2DefaulDataSource(JoinPoint pjp) throws Throwable{
DataSourceHolder.change2DefaulDataSource();
}
}
6.5测试
@Override
public TestQueryDTO findUserByUserCode(String userCode){
return testDao.findUserByUserCode(userCode);
}
@Override
@CustomDataSource(DataSourceHolder.MYSQL_DATA_SOURCE)
public TestQueryDTO findUserByUserCode2(String userCode){
return testDao.findUserByUserCode(userCode);
}
controller层调用这2个方法时将返回不同数据库中的数据