若依项目学习笔记07——数据源
1. 配置详解
在此之前,依旧是先去官方文档看其教程;我们已经在application.yml中配置了数据库连接池为druid,下面我们打开application-druid.yml来看看其中都配置了什么以及作用
- 必备三大件:url、username和passworld,这三个是必备的
- 主从数据库:我们这里只用了一个数据库,所以从数据库就设置为false,留着也是日后可以直接添加,方便一点;强烈注意:Spring Boot 2.X 版本不再支持配置继承,多数据源的话每个数据源的所有配置都需要单独配置,否则配置不会生效(下面有讲配置)
- 链接数:这部分大家看文档,暂时不去讲
- 数据监控:statViewServlet,对应本项目的 系统监控/数据监控 部分,其中 url-pattern 和 点击 系统监控/数据监控 的url是对应的;allow,设置白名单,在数据监控控制台能看到很多数据,其中有些是敏感数据,这是因为我们用于开发给开发人员看,才全部展示出来,这里可以设置白名单,让指定的url才能看;当然,这里也可以设置账号密码,要看数据则必须输入正确的账号密码
- SQL部分:慢SQL是指 数据监控/SQL监控 ,这里能看到SQL语句的执行情况,可以用来判断sql语句的效率;merge-sql表示如果sql监控有多个sql语句的执行情况一致则合并显示;multi-statement-allow表示允许多条sql语句批量执行,如mapper文件中,一个
<delete
下有一个delete语句,开启后,则可以有多个delete语句批量执行
2. 源码介绍
我们打开 framework.config.DruidConfig ,我们在这里配置了多数据源
2.1 创建数据源
@Bean
@ConfigurationProperties("spring.datasource.druid.master")//master代表主数据源
public DataSource masterDataSource(DruidProperties druidProperties)
{
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
return druidProperties.dataSource(dataSource);
}
DruidProperties
中定义了数据库连接相关的属性,可以点进去看一下,都是和配置文件中一一对应的
创建从数据源和创建主数据源基本一致(slave代表从数据源),只是多了一个步骤,即加了注解 @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
这是spring boot的常用配置注解,这里定义了配置的前缀为 spring.datasource.druid.slave ,名称为 enable ,值为 true ,我们在druid配置文件中设置的是false,所以从数据源无效
2.2 初始化所创建数据源
@Bean(name = "dynamicDataSource")
@Primary
public DynamicDataSource dataSource(DataSource masterDataSource)
{
Map<Object, Object> targetDataSources = new HashMap<>();
//加入主数据源
targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
//获取并加入从数据源
setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
//将主从数据源返回到一个新对象-动态数据源
return new DynamicDataSource(masterDataSource, targetDataSources);
}
2.3 去广告
默认的druid的数据监控页面的底部是有广告的
这里就用 removeDruidFilterRegistrationBean()
方法将其去除;略
3. 多数据源配置
3.1 切换多数据源
如果我们的项目改造成访问多个数据源的话,这时候就需要去切换数据源了,具体步骤如下
- 创建目标数据库(废话)
- 在druid配置文件中设置从数据源
- (关键)在需要切换数据源 Service 或 Mapper 方法上添加
@DataSource
注解(放在类上也可,这样就整个类都使用这个数据源);例如方法a要连接从数据源,就在上面加@DataSource(value = DataSourceType.SLAVE)
,反之用主数据库则改成MASTER
3.2 新增多数据源(同数据库类型)
如果你很闲,又需要访问第三个数据库,怎么办?那就来添加一个数据源吧,方法很简单,直接模仿多数据源的配置即可,下面是步骤
- 创建第三个数据库(( ̄_, ̄ ))
- 添加配置,直接copy从数据库 slave ,然后把他的名称改为 slave2 ,剩下配置按需填写
- 修改druid配置文件,还是一样,copy从数据库 slave 的方法,改成
slaveDataSource2()
,然后把里面的 slave 都加上2,就像这样
@Bean
@ConfigurationProperties("spring.datasource.druid.slave2")
@ConditionalOnProperty(prefix = "spring.datasource.druid.slave2", name = "enabled", havingValue = "true")
public DataSource slaveDataSource2(DruidProperties druidProperties)
{
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
return druidProperties.dataSource(dataSource);
}
然后去 dataSource()
方法把刚创建的 slave2 数据源加进来,setDataSource(targetDataSources, DataSourceType.SLAVE2.name(), "slaveDataSource2")
,这里要注意的是,我们要进入枚举类 DataSourceType 中加入第三个数据源的标识 SLAVE2(直接ctrl + 左键 点击 SLAVE 即可进入修改)
- 然后到对应的目标类或方法加上注解
@DataSource(value = DataSourceType.SLAVE2)
即可
3.3 新增多数据源(不同数据库类型)
如果多数据源还不能满足你,你还要别的类型的数据源,咋办?盘她~这里有两个问题,我们一般都是mysql,比如我们新数据源是sqlserver或者别的,在配置文件中如何配置;还有就是我们的pagehelper设置的是mysql,这又这么搞?下面就来分别解决
- 添加对应数据库依赖,如oracle
<!--oracle驱动-->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
- 修改配置文件,这里我们可以直接把
driverClassName: com.mysql.cj.jdbc.Driver
删掉,因为spring boot会自动识别,然后模仿slave继续copy,然后添加相应配置
# 从库数据源
slave:
# 从数据源开关/默认关闭
enabled: true
url: jdbc:oracle:thin:@127.0.0.1:1521:oracle
username: root
password: password
到后面如果报url的ORCL错误,大家可以把url的oracle改成orcl
- 修改pagehelper配置,把
helperDialect: mysql
删除,因为这个会自动识别驱动,然后添加autoRuntimeDialect=true
,标识运行时获取数据源 - 搞定~
3. 多数据源源码详解
我们打开 framework.aspectj.DataSourceAspect ,具体讲解在注释中
@Aspect//定义切面类
@Order(1)
@Component
public class DataSourceAspect
{
protected Logger logger = LoggerFactory.getLogger(getClass());
@Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)"
+ "|| @within(com.ruoyi.common.annotation.DataSource)")//匹配类上或者方法上是否有DataSource,就像前面几个小节中展示的
public void dsPointCut()
{
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable
{
DataSource dataSource = getDataSource(point);//获取数据源,见下
if (StringUtils.isNotNull(dataSource))
{
DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());//获取DataSource 注解中value的值,判断是什么数据库
}
try
{
return point.proceed();//值用目标数据库
}
finally
{
// 销毁数据源 在执行方法之后
DynamicDataSourceContextHolder.clearDataSourceType();
}
}
/**
* 获取需要切换的数据源
*/
public DataSource getDataSource(ProceedingJoinPoint point)
{
MethodSignature signature = (MethodSignature) point.getSignature();
DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);//获取类上的DataSource注解
if (Objects.nonNull(dataSource))//如果类上没有,则返回方法上的
{
return dataSource;
}
return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
}
}
值得一提的是,获取数据源信息的方法就在
DynamicDataSourceContextHolder
类中,有个getDataSourceType()
方法,大家自己去康康