应用场景

系统用户只能访问系统配置的数据源(可动态新增修改的)

RuoYi Vue 框架源码

点我跳转

实现方式

1.系统提供

Yml文件配置 + Druid加载数据源 + @DataSource注解 + DataSourceAspect增强

@DataSource 可以应用在类或方法上,如果同时存在,优先于方法上声明的数据源

// DataSourceType.MASTER 是一个枚举类里声明的主数据源
@DataSource(DataSourceType.MASTER)
public Map<String, Object> queryAll() {
// body
}

DataSourceAspect 实现功能主要代码:

// 切换数据源 dataSource.value().name() 就是@DataSource注解所使用的数据源名称
DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name()); // 销毁数据源 在执行方法之后
DynamicDataSourceContextHolder.clearDataSourceType();

2.自定义实现

Yml文件配置 + Druid加载数据源(下面有新增数据源方法) + @CustomDataSource注解 + CustomDataSourceAspect增强

Yml文件配置与上一实现方式中无差别,配置一个或多个正常使用的数据源。

Druid加载会在 SpringBootApplication 启动装配Bean时自动注入。

/**
* 新增数据源
* @param newDataSource 新数据源配置类
* @return boolean 是否添加成功
*/
public static boolean addDataSource(DruidDataSource newDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>();
boolean result = true;
try {
// 获取 yml 文件里已经注入进去的bean
targetDataSources.put(DataSourceType.MASTER.name(), SpringUtils.getBean("masterDataSource"));
targetDataSources.put("otherDataSource", SpringUtils.getBean("otherDataSource")); // DataSource 数据源相关配置
newDataSource.setDbType("com.alibaba.druid.pool.DruidDataSource");
newDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
newDataSource.setName("newDataSource");
newDataSource.setUrl("数据源URL");
newDataSource.setUsername("用户名");
newDataSource.setPassword("密码");
targetDataSources.put("newDataSource", newDataSource); DynamicDataSource dynamicDataSource = SpringUtils.getBean("dynamicDataSource");
dynamicDataSource.setTargetDataSources(targetDataSources); // 重新加载数据源
dynamicDataSource.afterPropertiesSet();
} catch (Exception e) {
// 处理异常 ...
logger.error("新增数据源错误")
result = false;
} return result;
}

定义 @CustomDataSource 注解

import java.lang.annotation.*;

/**
* 自定义多数据源切换注解可声明在类上或声明在方法上
* 如果定义在类上则本类全部方法都会进行数据源切换处理
* 如果定义在方法上则数据源切换只应用于方法上
*
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface CustomDataSource { }

定义 CustomDataSourceAspect 增强

import com.ruoyi.common.annotation.TestDataSource;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder;
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 java.util.Objects; /**
* 多数据源处理
*
*/
@Aspect
@Order(1)
@Component
public class CustomDataSourceAspect {
protected Logger logger = LoggerFactory.getLogger(getClass()); @Pointcut("@annotation(com.ruoyi.common.annotation.CustomDataSource)"
+ "|| @within(com.ruoyi.common.annotation.CustomDataSource)")
public void customPointCut() { } @Around("customPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
CustomDataSource dataSource = getDataSource(point);
if (StringUtils.isNotNull(dataSource)) {
// 根据当前用户查询数据源并切换数据源
LoginUser loginUser = SecurityUtils.getLoginUser();
String dataSourceType = "实际配置的数据源名称";
// 切换数据源
DynamicDataSourceContextHolder.setDataSourceType(dataSourceType);
} try {
return point.proceed();
} finally {
// 销毁数据源 在执行方法之后
DynamicDataSourceContextHolder.clearDataSourceType();
}
} /**
* 获取需要切换的数据源
*/
public TestDataSource getDataSource(ProceedingJoinPoint point) {
MethodSignature signature = (MethodSignature) point.getSignature();
TestDataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), TestDataSource.class);
if (Objects.nonNull(dataSource)) {
return dataSource;
} return AnnotationUtils.findAnnotation(signature.getDeclaringType(), CustomDataSource.class);
}
}

tips:

// 修改默认数据源方式
dynamicDataSource.setDefaultTargetDataSource(数据源配置类);

至此系统用户登录后发送请求,如果存在 CustomDataSourc 注解则会根据查询被分配的数据源,否则查询主数据源(master)的数据

【必看】RuoYiVuek框架-数据源动态新增、配置如此简单!的更多相关文章

  1. java:Spring框架1(基本配置,简单基础代码模拟实现,spring注入(DI))

    1.基本配置: 步骤一:新建项目并添加spring依赖的jar文件和commons-logging.xx.jar: 步骤二:编写实体类,DAO及其实现类,Service及其实现类; 步骤三:在src下 ...

  2. Yii1.1框架关于日志的配置的简单使用

    最近开始接触新项目,新项目用的框架是Yii1.1版本的,通过看框架文档大致熟悉了解了Yii在日志方面的使用. 首先在protected/config/main.php配置文件中加入日志相关配置,如下图 ...

  3. C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志

    C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...

  4. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  5. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  6. Spring3 整合MyBatis3 配置多数据源 动态选择SqlSessionFactory

    一.摘要 上两篇文章分别介绍了Spring3.3 整合 Hibernate3.MyBatis3.2 配置多数据源/动态切换数据源 方法 和 Spring3 整合Hibernate3.5 动态切换Ses ...

  7. Mysql数据库优化技术之配置篇、索引篇 ( 必看 必看 转)

    转自:Mysql数据库优化技术之配置篇.索引篇 ( 必看 必看 ) (一)减少数据库访问对于可以静态化的页面,尽可能静态化对一个动态页面中可以静态的局部,采用静态化部分数据可以生成XML,或者文本文件 ...

  8. VC++6.0使用OpenGL前的配置(必看)

    要在VC++6.0中使用opengl,需要配置一下环境设置. 具体需要两步: 1.加入一个头文件,两个lib文件,两个dll文件,放在合适位置. 2.配置一下vc++6.0的Project Setti ...

  9. Springboot多数据源配置--数据源动态切换

    在上一篇我们介绍了多数据源,但是我们会发现在实际中我们很少直接获取数据源对象进行操作,我们常用的是jdbcTemplate或者是jpa进行操作数据库.那么这一节我们将要介绍怎么进行多数据源动态切换.添 ...

  10. JavaWeb_(Struts2框架)struts.xml核心配置、动态方法调用、结果集的处理

    此系列博文基于同一个项目已上传至github 传送门 JavaWeb_(Struts2框架)Struts创建Action的三种方式 传送门 JavaWeb_(Struts2框架)struts.xml核 ...

随机推荐

  1. ORM数据增删改查 django请求生命周期 django路由层 反向解析

    目录 可视化界面之数据增删改查 补充 1.建表 2.数据展示功能 3.数据添加功能 4.数据编辑功能 5.数据删除功能 django请求生命周期流程图 crsf wsgirel 与 uwsgi ngi ...

  2. 我做了第一个ChatGPT .net api聊天库

    最近这个ChatGPT很火啊,看了B站上很多视频,自己非常手痒,高低自己得整一个啊,但是让我很难受的是,翻遍了github前十页,竟然没有一个C#的ChatGPT项目,我好难受啊!那能怎么办?自己搞一 ...

  3. redis集合 实现 队列

    先说一下需求:用队列解决 流量削峰,主要应用场景:商城秒杀功能. 以下是业务流程图可以参考一下: 然后本地实现思路 截图下单页面 每次购买数量会减少1,设置了1000个库存,用户id 是随机生成的. ...

  4. 架构设计(四):CDN

    架构设计(四):CDN 作者:Grey 原文地址: 博客园:架构设计(四):CDN CSDN:架构设计(四):CDN CDN 全称 Content delivery network ,即:内容分发网络 ...

  5. jmeter 之性能分布式压测

    背景: 当并发量达到一定数量时,单台测试设备不足以支撑,甚至会出现内存溢出等情况,解决这个问题就可用分布式测试,使用多台测试设备来达到更大的用户并发数. 原理: 1.一台设备作为调度机(master) ...

  6. 含辞未吐,声若幽兰,史上最强免费人工智能AI语音合成TTS服务微软Azure(Python3.10接入)

    所谓文无第一,武无第二,云原生人工智能技术目前呈现三足鼎立的态势,微软,谷歌以及亚马逊三大巨头各擅胜场,不分伯仲,但目前微软Azure平台不仅仅只是一个PaaS平台,相比AWS,以及GAE,它应该是目 ...

  7. 【转载】EXCEL VBA 自动筛选—AutoFilter方法

    AutoFilter方法的语法及说明   下面是Range对象的AutoFilter方法的语法:      Range对象.AutoFilter(Field,Criterial1,Operator,C ...

  8. [OpenCV实战]27 在OpenCV下使用forEach进行并行像素访问

    目录 1 Mat像素访问 1.1 使用at方法直接进行像素访问 1.2 使用指针进行像素访问 1.3 使用forEach方法进行像素访问 1.4 将forEach与C ++ 11 Lambda一起使用 ...

  9. Exception in thread &amp;quot;main&amp;quot; java.lang.ArrayIndexOutOfBoundsException: 1

    场景:eclipse中编写java中用到数组 问题: 程序不报错但是运行过程中 终止,显示字样 " Exception in thread "main" java.lan ...

  10. BC4-牛牛学说话之-浮点数

    题目描述 会说整数之后,牛牛开始尝试浮点数(小数),输入一个浮点数,输出这个浮点数. 输入描述 输入一个浮点数 输出描述 输出一个浮点数,保留三位小数 示例 1 输入:1.359578 输出:1.36 ...