最近由于项目需求,需要将Sql Server 和 Mysql 两种数据库整合到一个项目,项目的用到的框架是SSM。 因此尝试了利用AOP切面来切每次执行的Servcie方法,根据Service所在的包名来实现数据源自动切换。

  1.项目架构如下:

  

  2.在com.jiefupay.database包中建立四个类:

      

    其中 DataSourceContextHolder.java类源码如下:    

package com.jiefupay.datebase;

public class DataSourceContextHolder {

     private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
  //设置当前Thread的数据库类型
public static void setDbType(String dbType) {
contextHolder.set(dbType);
}
//获取当前Thread的数据库类型
public static String getDbType() {
return ((String) contextHolder.get());
} public static void clearDbType() {
contextHolder.remove();
} }

    其中,DataSourceName.java源码如下:

package com.jiefupay.datebase;

/**
* 数据库名称常量类
*/
public class DataSourceName { public static final String SQLSERVER_SOURCE = "sqlserver_source";
public static final String MYSQL_SOURCE = "mysqlSource";
}

    其中,DynamicDataSource.java源码如下:

package com.jiefupay.datebase;

import java.util.logging.Logger;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {

     @Override
public Logger getParentLogger() {
return null;
} @Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDbType();
}
}

    其中,ChangeDBInteceptor.java作为切点的拦截类,获取每次执行的service的全限令名,源码如下:

package com.jiefupay.datebase;

import org.aspectj.lang.ProceedingJoinPoint;

public class ChangDBInterceptor {

    public Object changeDB(ProceedingJoinPoint pjp) throws Throwable {
//AOP切点在Service的 包名.类名
String path=pjp.getTarget().getClass().getName();
//如果servcie的 包名.类名 包含 agency,那说明需要切换为mysql数据源
if (path.indexOf("agency")!=-1){
DataSourceContextHolder.setDbType(DataSourceName.MYSQL_SOURCE);
}else{
DataSourceContextHolder.setDbType(DataSourceName.SQLSERVER_SOURCE);
}
return pjp.proceed();
} }

  3.jdbc.properties文件如下:

mysqldriver=com.mysql.jdbc.Driver
mysqlurl=jdbc:mysql://192.168.0.144:3306/mysql?useUnicode=true&characterEncoding=UTF-8
mysqlusername=myusername
mysqlpassword=mypassword driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
url=jdbc:sqlserver://192.168.0.144:1433;databaseName=sqlserver_source
username=sqlusername
password=sqlpassword #定义初始连接数
initialSize=4
#定义最大连接数
maxActive=6
#定义最大空闲
maxIdle=2
#定义最小空闲
minIdle=2
#定义最长等待时间
maxWait=60000

  

  4.spring-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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-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/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> <!-- 自动扫描 -->
<context:component-scan base-package="com.jiefupay" >
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan> <!-- 引入配置文件 -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties" />
</bean> <!-- 多数据源配置 -->
<bean id ="sqlserver_source" class= "org.apache.commons.dbcp.BasicDataSource" >
<property name ="driverClassName" value= "${driver}"></property >
<property name ="url" value="${url}" ></property >
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<property name="initialSize" value="${initialSize}"></property>
<property name="maxActive" value="${maxActive}"></property>
<property name="maxIdle" value="${maxIdle}"></property>
<property name="minIdle" value="${minIdle}"></property>
<property name="maxWait" value="${maxWait}"></property>
</bean >
<bean id="mysqlSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${mysqldriver}" />
<property name="url" value="${mysqlurl}" />
<property name="username" value="${mysqlusername}" />
<property name="password" value="${mysqlpassword}" />
<property name="initialSize" value="${initialSize}"></property>
<property name="maxActive" value="${maxActive}"></property>
<property name="maxIdle" value="${maxIdle}"></property>
<property name="minIdle" value="${minIdle}"></property>
<property name="maxWait" value="${maxWait}"></property>
</bean> <!-- 动态配置数据源 -->
<bean id ="dataSource" class= "com.jiefupay.datebase.DynamicDataSource" >
<property name ="targetDataSources">
<map key-type ="java.lang.String">
<entry value-ref ="newdata_2014" key="sqlserver_source"></entry >
<entry value-ref ="mysqlSource" key="mysqlSource"></entry >
</map>
</property >
<property name ="defaultTargetDataSource" ref= "sqlserver_source"></property >
</bean > <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:com/jiefupay/*/mapper/*.xml"></property>
</bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.jiefupay.*.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean> <bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean> <tx:annotation-driven transaction-manager="transactionManager"/> <bean id="changeDBInterceptor" class="com.jiefupay.datebase.ChangDBInterceptor"></bean> <!-- 配置AOP切面,所有service作为切点,执行changeDBInterceptor类中的changeDB方法 -->
<aop:config proxy-target-class="true">
<aop:pointcut id="txPointcut" expression="execution(* com.jiefupay..service..*Service*.*(..)) or execution(* com.jiefupay.common..*Service*.*(..))" />
<aop:aspect ref="changeDBInterceptor" order="1">
<aop:around pointcut-ref="txPointcut" method="changeDB"/>
</aop:aspect>
</aop:config> </beans>

Spring MVC动态切换数据源(多数据库类型)的更多相关文章

  1. Spring+Mybatis动态切换数据源

    功能需求是公司要做一个大的运营平台: 1.运营平台有自身的数据库,维护用户.角色.菜单.部分以及权限等基本功能. 2.运营平台还需要提供其他不同服务(服务A,服务B)的后台运营,服务A.服务B的数据库 ...

  2. Spring AOP动态切换数据源

    现在稍微复杂一点的项目,一个数据库也可能搞不定,可能还涉及分布式事务什么的,不过由于现在我只是做一个接口集成的项目,所以分布式就先不用了,用Spring AOP来达到切换数据源,查询不同的数据库就可以 ...

  3. Spring学习总结(16)——Spring AOP实现执行数据库操作前根据业务来动态切换数据源

    深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...

  4. spring mvc+mybatis+多数据源切换

    spring mvc+mybatis+多数据源切换,选取oracle,mysql作为例子切换数据源.oracle为默认数据源,在测试的action中,进行mysql和oracle的动态切换. web. ...

  5. Spring + Mybatis 项目实现动态切换数据源

    项目背景:项目开发中数据库使用了读写分离,所有查询语句走从库,除此之外走主库. 最简单的办法其实就是建两个包,把之前数据源那一套配置copy一份,指向另外的包,但是这样扩展很有限,所有采用下面的办法. ...

  6. Spring动态切换数据源及事务

    前段时间花了几天来解决公司框架ssm上事务问题.如果不动态切换数据源话,直接使用spring的事务配置,是完全没有问题的.由于框架用于各个项目的快速搭建,少去配置各个数据源配置xml文件等.采用了动态 ...

  7. Spring Boot 如何动态切换数据源

    本章是一个完整的 Spring Boot 动态数据源切换示例,例如主数据库使用 lionsea 从数据库 lionsea_slave1.lionsea_slave2.只需要在对应的代码上使用 Data ...

  8. 在使用 Spring Boot 和 MyBatis 动态切换数据源时遇到的问题以及解决方法

    相关项目地址:https://github.com/helloworlde/SpringBoot-DynamicDataSource 1. org.apache.ibatis.binding.Bind ...

  9. hibernate动态切换数据源

    起因: 公司的当前产品,主要是两个项目集成的,一个是java项目,还有一个是php项目,两个项目用的是不同的数据源,但都是mysql数据库,因为java这边的开发工作已经基本完成了,而php那边任务还 ...

随机推荐

  1. NestedScrollView嵌套RecycleView 滑动 实现上滑隐藏 下滑显示头部效果

    废了好大的劲才弄好的,记下来 方便以后查看 public class MainActivity extends AppCompatActivity { private RecyclerView mRe ...

  2. 纯JS实现图片验证码功能并兼容IE6-8

    最近要搞一个图片验证码功能,但是又不想自己写后台代码.于是自己准备搞一个纯前端的验证码功能,于是网上搜索了一下,找到一个插件gVerify.js,简单好用,实现完美.不过后面接到说要兼容IE8,想想也 ...

  3. LINQ to XML编程之编程基础

    1.声明,LINQ to XML让xml的创建变得非常简单. XDocument myDocument = new XDocument( new XDeclaration("1.0" ...

  4. CF IndiaHacks 2016 F Paper task 后缀数组

    题目链接:http://codeforces.com/problemset/problem/653/F 大意是给出一个只包含'('和')'的括号串,求有多少不同的子串是合法的括号串 解法:对于每一个后 ...

  5. IDEA第三章----idea常用配置

    前两章讲解了idea的git.maven.jdk.tomcat.编码等基本配置,可以让你的项目正常运行,这一章将讲解idea的一些常用设置,这些也正是idea可爱之处,大大提高了开发的效率. 第一节: ...

  6. 单Js 的重力游戏开发

    最近在用看cocos的时候萌生的想法,单纯js实现重力原理.然后就做了一个这样的小游戏.姑且命名为<超级玛丽>! 因为之前有人要我做超级玛丽.哈哈哈哈哈哈!这也算完成任务了吧. 先说一下原 ...

  7. [ext4]09 磁盘布局 - superblock备份机制

    如果sparse_super特性flag被设置(即开启了sparse_super特性),那么super_block和组描述符的副本只会保存在group索引为0或3.5.7的整数幂. 如果没有设置spa ...

  8. poj3160强连通分量加dfs

    After retirement as contestant from WHU ACM Team, flymouse volunteered to do the odds and ends such ...

  9. 腾讯QQAndroid API调用实例(QQ分享无需登录)

    腾讯QQAndroid API调用实例(QQ分享无需登录)   主要分为两个步骤: 配置Androidmanifest.xml 修改activity里边代码 具体修改如下:   1.Activity代 ...

  10. 九思老客户分享:部署OA办公系统的四大意义

    原文:http://www.jiusi.net/detail/472__776__4009__1.html 关键词:OA办公系统.oa系统 .九思OA 九思老客户分享:部署OA办公系统的四大意义 当今 ...