spring mybatis 多数据源配置 jeesite 多数据源配置

一、情景描述

在系统数据达到一定的访问量时,遇到单个数据库瓶颈,所以需要扩展数据库,启用第二个数据源资源,项目架构变成 一个服务对应多个数据源的形式。

二、步骤

1、原理:org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource,实现动态数据源的切换。

2、创建 DynamicDataSource 继承 AbstractRoutingDataSource , 重写 determineCurrentLookupKey 方法,配置数据源切换

3、创建 DataSourceEnum 定义数据源类型

4、创建 DataSourceHolder ,提供数据源切换

5、创建多个数据源 JK , SEC

6、配置到 DynamicDataSource 中

7、同步调 配置文件中数据源改为: dynamicDataSource

  • org.mybatis.spring.SqlSessionFactoryBean (spring-context.xml 文件中)
  • org.springframework.jdbc.datasource.DataSourceTransactionManager (spring-context.xml 文件中)
  • org.activiti.spring.SpringProcessEngineConfiguration (spring-context-activiti.xml)

8、在Controller中,使用: DataSourceHolder.setDataSource(DataSourceEnum.SEC); 可实现数据源的切换。

9、实现数据源动态切换:

  • 定义 DataSource 注解
  • 配置AOP切面: DataSourceAspect
  • 在 Controller方法上,使用 @DataSource(DataSourceEnum.SEC) 注解,实现数据源的切换

10、遗留问题:在Service层,切换数据源无效,经过日志打印发现,在从 Controller 进入到Service时,会调用数据源 , 之后可以进行切换,但是遇到切换无效 ... 个人推测,是因为 Service 继承的 Dao层的缘故 ... 问题有待确认!

三、代码实现

1、创建 DynamicDataSource 类

import java.util.Map;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/*** description: 动态数据源切换* @version v1.0* @author w* @date 2021年5月7日下午2:56:09**/
public class DynamicDataSource extends AbstractRoutingDataSource {private static final Logger logger = LoggerFactory.getLogger(DynamicDataSource.class);public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {super.setDefaultTargetDataSource(defaultTargetDataSource);super.setTargetDataSources(targetDataSources);super.afterPropertiesSet();}public DynamicDataSource() {}@Overrideprotected Object determineCurrentLookupKey() {logger.info("use dataSource , {}" , DataSourceHolder.getDataSource());return DataSourceHolder.getDataSource();}
}

2、创建 DataSourceEnum 定义数据源类型

/*** description: 数据源类型* @version v1.0* @author w* @date 2021年5月10日下午3:40:07**/
public enum DataSourceEnum {/*** 默认数据源JK*/JK ,/*** 第二个数据源*/SEC ;
}

3、创建 DataSourceHolder ,提供数据源切换

import com.thinkgem.jeesite.common.persistence.enums.DataSourceEnum;/*** description: 数据源提供* @version v1.0* @author w* @date 2021年5月10日下午2:44:22**/
public class DataSourceHolder {private static final ThreadLocal<String> CONTAINER = new ThreadLocal<String>();public static String getDataSource() {return CONTAINER.get();}public static void setDataSource(String type) {CONTAINER.set(type);}public static void setDataSource(DataSourceEnum dataSourceEnum) {CONTAINER.set(dataSourceEnum.name());}public static void clearDataSource() {CONTAINER.remove();}}

4、创建多个数据源 JK , SEC

<bean id="secDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}" />... 略 ...

5、配置到 DynamicDataSource 中

<bean id="dynamicDataSource" class="com.thinkgem.jeesite.common.persistence.DynamicDataSource"><property name="targetDataSources"><map key-type="java.lang.String"><description>build dataSource key value mapping</description><entry key="JK" value-ref="jkDataSource"></entry><entry key="SEC" value-ref="secDataSource"></entry></map></property><property name="defaultTargetDataSource" ref="jkDataSource"></property>
</bean>

6、同步调整:spring-context.xml 中,原 dataSource 调整为 dynamicDataSourcespring-context-activiti.xmldataSource 调整为 dynamicDataSource

7、创建 DataSource 注解

*** description: 切换数据源的注解* @version v1.0* @author w* @date 2021年5月10日下午3:42:14**/
@Target(value = { ElementType.METHOD , ElementType.TYPE })
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DataSource {/*** description: 实现数据源的切换* @return DataSourceEnum* @version v1.0* @author w* @date 2021年5月10日 下午3:45:40*/DataSourceEnum value() default DataSourceEnum.JK ;
}

8、创建 DataSourceAspect 类,配置AOP切面 (需要在 spring-mvc.xml 文件中,配置启用注解 <aop:aspectj-autoproxy/>

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.thinkgem.jeesite.common.persistence.DataSourceHolder;
import com.thinkgem.jeesite.common.persistence.annotation.DataSource;/*** description: 数据源的切面 配置* @version v1.0* @author w* @date 2021年5月10日下午4:09:17**/
@Component
@Order(10)
@Aspect
public class DataSourceAspect {private static final Logger logger = LoggerFactory.getLogger(DataSourceAspect.class);/*** description: 配置切点* @return void* @version v1.0* @author w* @date 2021年5月10日 下午4:13:32*/@Pointcut(value = "@annotation(com.thinkgem.jeesite.common.persistence.annotation.DataSource)"+"|| @within(com.thinkgem.jeesite.common.persistence.annotation.DataSource)")public void pointCut() {}/*** description: 配置环绕 * @param point* @throws Throwable* @return Object* @version v1.0* @author w* @date 2021年5月10日 下午4:25:51*/@Around("pointCut()")public Object around(ProceedingJoinPoint point) throws Throwable {MethodSignature methodSignature = (MethodSignature)point.getSignature();DataSource annotation = methodSignature.getMethod().getAnnotation(DataSource.class);if(null != annotation) {DataSourceHolder.setDataSource(annotation.value().name());logger.info("数据源切换成功~~ use dataSource , {}" , annotation.value());}else {// 尝试从类上获取DataSource findAnnotation = AnnotationUtils.findAnnotation(methodSignature.getDeclaringType(), DataSource.class);if(null != findAnnotation) {DataSourceHolder.setDataSource(findAnnotation.value().name());logger.info("数据源切换成功~~ use dataSource findAnnotation , {}" , findAnnotation.value());}}try {return   point.proceed();} finally {DataSourceHolder.clearDataSource();}}}

9、在Controller中的方法上,使用 @DataSource(DataSourceEnum.SEC) 注解,即可实现数据源切换。

    @DataSource(DataSourceEnum.SEC)@RequestMapping(value = {"list", ""})@ResponseBodypublic ResultVO list(args...) {return ResultVO.success(page);}

四、总结

1、使用Spring提供的 AbstractRoutingDataSource 类,实现数据源的切换。

2、使用Spring AOP 实现,动态数据源切换,避免在Controller中硬编码。

参考资料:Spring, MyBatis 多数据源的配置和管理

【Mybatis】MyBatis之配置多数据源(十)

ThreadLocal作用理解

spring mybatis 多数据源配置 jeesite 多数据源配置相关推荐

  1. [转载]spring+mybatis加载属性文件设置数据源失败原因及解决方案 - 泡在网上的日子

    spring+mybatis加载属性文件设置数据源失败原因及解决方案 - 泡在网上的日子 http://www.jcodecraeer.com/a/chengxusheji/java/2013/062 ...

  2. java spring mysql配置_java相关:mysql+spring+mybatis实现数据库读写分离的代码配置

    java相关:mysql+spring+mybatis实现数据库读写分离的代码配置 发布于 2020-4-4| 复制链接 分享一篇关于关于mysql+spring+mybatis实现数据库读写分离的代 ...

  3. Eclipse+Maven+Struts2+Spring+Mybatis完整搭建

    一.前言 公司框架是SSH,hibernate用的越来越少,做了几年后,也懒得用了,springjdbc玩到现在,maven,mybatis没用到一直都没去接触,感慨现在技术真是发展越来越快,有点落伍 ...

  4. Spring+MyBatis 多数据源配置和切换

    两台 MySQL 数据库(属于 master-slave 主从关系),基于 Java8,Spring4,MyBatis3.2 环境. maven 依赖配置 <dependencies>&l ...

  5. Spring+Mybatis多数据源配置(一)——MySQL与Oracle通过配置切换

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  6. Spring, MyBatis 多数据源的配置和管理

    同一个项目有时会涉及到多个数据库,也就是多数据源.多数据源又可以分为两种情况: 1)两个或多个数据库没有相关性,各自独立,其实这种可以作为两个项目来开发.比如在游戏开发中一个数据库是平台数据库,其它还 ...

  7. Spring 学习系列 -- Spring + Mybatis 从零开始配置多数据源访问

    目的: 项目中以前有整合mybatis + spring操作数据库,但是以前都是单数据库,现需要实现mybatis访问多数据源,依旧使用spring调用mybatis. 通过注解的方式整合 sprin ...

  8. Spring+MyBatis多数据源配置实现

    最近用到了MyBatis配置多数据源,原以为简单配置下就行了,实际操作后发现还是要费些事的,这里记录下,以作备忘 不多废话,直接上代码,后面会有简单的实现介绍 jdbc和log4j的配置 #定义输出格 ...

  9. 【教程】Spring+Mybatis环境配置多数据源

    做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 文章目录 一.简要概述 二.代码详解 2.1 `DataSourceConstants` 数据源常量类 2.2 `Data ...

最新文章

  1. 第十三周项目4-数组的排序:冒泡排序
  2. 强交变磁场下的AD转换数值的变化
  3. 解决SVN 每次操作都需要重输入用户名密码问题
  4. 03构建之法阅读笔记之三
  5. 倒数日怎么显示在桌面_深圳暴风谷滑梯皮带提升机怎么选
  6. 2.3.6 操作系统之进程同步与互斥经典问题(生产者-消费者问题、多生产者-多消费者问题、吸烟者问题、读者-写者问题、哲学家进餐问题)
  7. 【连载】如何掌握openGauss数据库核心技术?秘诀五:拿捏数据库安全(4)
  8. python主函数入口_python类 + mian()函数
  9. 阿里云网盘内测_叫板百度网盘?阿里云网盘内测中,下载速度是亮点
  10. sv信道模型是什么_信道模型(信道模型分类)
  11. 怎样黑网吧的万象系统_5636小编教你如何进入万象网管系统
  12. Js 获取浏览器高度
  13. AttributeError:partially initialized module ''has no attribute''(most likely dueto a circular import
  14. Aifred、Wox免费开源的效率启动器
  15. 【QA单】柿饼派及柿饼M3模块相关QA(持续更新....)
  16. python数据标准_python-StandardScaler数据标准化
  17. UVa12325 宝藏
  18. [CQOI2005]三角形面积并
  19. 浅谈:智能化变电站在线监测系统
  20. Windows本地连接正常,上不去网的解决办法

热门文章

  1. 代理模式与三种方式实现SpringAOP!
  2. Java检测IP地址输入是否正确
  3. attr()和prop()的区别
  4. 新计算机的windows要不要不断更新,win10一直出现无法完成更新正在撤销更改请不要关闭你的计算机,怎么办?...
  5. 如何取消掉计算机更新图标,本文演示win10电脑更新图标怎么去掉的具体操作方式...
  6. 指纹图像方向图matlab,基于Matlab实现的指纹图像细节特征提取
  7. 【转载】那个裸辞的程序员,后来怎么样了?
  8. Studio 3T的使用
  9. 桌面便利贴软件下载 电脑桌面便签小工具软件下载
  10. python midi_Python | 读取 midi 文件