若依项目学习笔记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 中定义了数据库连接相关的属性,可以点进去看一下,都是和配置文件中一一对应的
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 切换多数据源

如果我们的项目改造成访问多个数据源的话,这时候就需要去切换数据源了,具体步骤如下

  1. 创建目标数据库(废话)
  2. 在druid配置文件中设置从数据源
  3. (关键)在需要切换数据源 Service 或 Mapper 方法上添加 @DataSource 注解(放在类上也可,这样就整个类都使用这个数据源);例如方法a要连接从数据源,就在上面加 @DataSource(value = DataSourceType.SLAVE) ,反之用主数据库则改成 MASTER

3.2 新增多数据源(同数据库类型)

如果你很闲,又需要访问第三个数据库,怎么办?那就来添加一个数据源吧,方法很简单,直接模仿多数据源的配置即可,下面是步骤

  1. 创建第三个数据库(( ̄_, ̄ ))
  2. 添加配置,直接copy从数据库 slave ,然后把他的名称改为 slave2 ,剩下配置按需填写
  3. 修改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 即可进入修改)

  1. 然后到对应的目标类或方法加上注解 @DataSource(value = DataSourceType.SLAVE2) 即可

3.3 新增多数据源(不同数据库类型)

如果多数据源还不能满足你,你还要别的类型的数据源,咋办?盘她~这里有两个问题,我们一般都是mysql,比如我们新数据源是sqlserver或者别的,在配置文件中如何配置;还有就是我们的pagehelper设置的是mysql,这又这么搞?下面就来分别解决

  1. 添加对应数据库依赖,如oracle
<!--oracle驱动-->
<dependency>
	<groupId>com.oracle</groupId>
	<artifactId>ojdbc6</artifactId>
	<version>11.2.0.3</version>
</dependency>

  1. 修改配置文件,这里我们可以直接把 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

  1. 修改pagehelper配置,把 helperDialect: mysql 删除,因为这个会自动识别驱动,然后添加 autoRuntimeDialect=true ,标识运行时获取数据源
  2. 搞定~

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() 方法,大家自己去康康

posted @ 2020-12-01 00:22  刘条条  阅读(718)  评论(0编辑  收藏  举报