Spring MVC动态切换数据源(多数据库类型)
最近由于项目需求,需要将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动态切换数据源(多数据库类型)的更多相关文章
- Spring+Mybatis动态切换数据源
功能需求是公司要做一个大的运营平台: 1.运营平台有自身的数据库,维护用户.角色.菜单.部分以及权限等基本功能. 2.运营平台还需要提供其他不同服务(服务A,服务B)的后台运营,服务A.服务B的数据库 ...
- Spring AOP动态切换数据源
现在稍微复杂一点的项目,一个数据库也可能搞不定,可能还涉及分布式事务什么的,不过由于现在我只是做一个接口集成的项目,所以分布式就先不用了,用Spring AOP来达到切换数据源,查询不同的数据库就可以 ...
- Spring学习总结(16)——Spring AOP实现执行数据库操作前根据业务来动态切换数据源
深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...
- spring mvc+mybatis+多数据源切换
spring mvc+mybatis+多数据源切换,选取oracle,mysql作为例子切换数据源.oracle为默认数据源,在测试的action中,进行mysql和oracle的动态切换. web. ...
- Spring + Mybatis 项目实现动态切换数据源
项目背景:项目开发中数据库使用了读写分离,所有查询语句走从库,除此之外走主库. 最简单的办法其实就是建两个包,把之前数据源那一套配置copy一份,指向另外的包,但是这样扩展很有限,所有采用下面的办法. ...
- Spring动态切换数据源及事务
前段时间花了几天来解决公司框架ssm上事务问题.如果不动态切换数据源话,直接使用spring的事务配置,是完全没有问题的.由于框架用于各个项目的快速搭建,少去配置各个数据源配置xml文件等.采用了动态 ...
- Spring Boot 如何动态切换数据源
本章是一个完整的 Spring Boot 动态数据源切换示例,例如主数据库使用 lionsea 从数据库 lionsea_slave1.lionsea_slave2.只需要在对应的代码上使用 Data ...
- 在使用 Spring Boot 和 MyBatis 动态切换数据源时遇到的问题以及解决方法
相关项目地址:https://github.com/helloworlde/SpringBoot-DynamicDataSource 1. org.apache.ibatis.binding.Bind ...
- hibernate动态切换数据源
起因: 公司的当前产品,主要是两个项目集成的,一个是java项目,还有一个是php项目,两个项目用的是不同的数据源,但都是mysql数据库,因为java这边的开发工作已经基本完成了,而php那边任务还 ...
随机推荐
- JavaScript高级程序设计---学习笔记(三)
函数表达式 定义函数的方式有两种:一种是函数声明,另一种是函数表达式. 关于函数声明,它的一个重要特征就是函数声明提升,意思是在执行代码之前会先读取函数声明所以可以把函数声明放在调用它的语句后面. 而 ...
- MCDownloader(iOS下载器)说明书
示例 前言 很多iOS应用中都需要下载数据,并对这些下载的过程和结果进行管理,因此我才有了写这个MCDownloader的想法.在IOS 文件下载器-MCDownloadManager这篇文章中,我使 ...
- JavaEE开发使用Maven管理的SpringMVC工程
前几篇博客已经陆陆续续的聊了一些Spring的东西,今天博客我们就来聊一下SpringMVC.SpringMVC目前在JavaEE开发中可谓占据一席之地,用起来也是比较顺手的.低耦合,高内聚,利用一些 ...
- 【机器学习】神经网络实现异或(XOR)
注:在吴恩达老师讲的[机器学习]课程中,最开始介绍神经网络的应用时就介绍了含有一个隐藏层的神经网络可以解决异或问题,而这是单层神经网络(也叫感知机)做不到了,当时就觉得非常神奇,之后就一直打算自己实现 ...
- Webdriver API之操作(一)
一. 控制浏览器 1. 控制浏览器大小 driver.set_window_size(480,800) #浏览器宽480,高800显示 dirver.maximize_window() #浏览器最大化 ...
- JQ实现选中以后就左右移动
<head> <meta charset="utf-8" /> <title>select_option移动</title> < ...
- 149_best-time-to-buy-and-sell-stock
/*@Copyright:LintCode@Author: Monster__li@Problem: http://www.lintcode.com/problem/best-time-to-b ...
- oracle 归档日志满 报错ORA-00257: archiver error. Connect internal only, until freed
归档日志满导致无法用户无法登陆 具体处理办法 --用户登陆 Microsoft Windows [Version 6.1.7601] Copyright (c) Microsoft Corporati ...
- SpringMVC4+MyBatis+SQL Server2014 基于SqlSession实现读写分离(也可以实现主从分离)
前言 上篇文章我觉的使用拦截器虽然方便快捷,但是在使用读串还是写串上你无法控制,我更希望我们像jdbc那样可以手动控制我使用读写串,那么这篇则在sqlsession的基础上实现读写分离, 这种方式则需 ...
- Python数据结构与循环语句
# Python数据结构与循环语句: 首先编程是一项技能,类似跑步,期初不必在意细节,能使用起来就行,等学的游刃有余了再回过头来关注细节问题也不迟. 关于买书: 学会python之后,才需要买书 ...