• yml配置动态数据源(数据库@DS)与引起(If you want an embedded database (H2, HSQL or Derby))类问题


    1:yml 配置

    spring:
      datasource:
        dynamic:
          datasource:
            master:
              url: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
              username: root
              password: root
              driver-class-name: com.mysql.cj.jdbc.Driver
            second-datasource:
              url: jdbc:mysql://192.168.11.50:3306/commons_utils?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
              username: root
              password: root
              driver-class-name: com.mysql.cj.jdbc.Driver
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2:必须pom依赖配

            
            <dependency>
                <groupId>com.baomidougroupId>
                <artifactId>dynamic-datasource-spring-boot-starterartifactId>
                <version>3.2.0version>
            dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2-1:不要加入一下依赖不然会报以下错误

            <dependency>
                <groupId>com.h2databasegroupId>
                <artifactId>h2artifactId>
                <version>1.4.200version>
                <scope>runtimescope>
            dependency>
    
            
            <dependency>
                <groupId>com.alibabagroupId>
                <artifactId>druid-spring-boot-starterartifactId>
                <version>1.2.6version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    2-2:当出现以上错误可以在yml配置文件去掉DruidDataSourceAutoConfigure,如下

    spring:
      autoconfigure:
        exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
    
    • 1
    • 2
    • 3

    3:加入数据库连接池druid依赖管理(使用多数据源一定要用链接池),Druid是阿里巴巴开源的一个数据库连接池和实时数据分析组件。相比其他连接池,Druid在功能特性、性能、监控等方面有很多优势,比如支持SQL解析、慢SQL日志、提供多维度监控等

    spring:
      autoconfigure:
        exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
      datasource:
        druid:
          stat-view-servlet:
            enabled: true
            loginUsername: admin
            loginPassword: 123456
            allow:
          web-stat-filter:
            enabled: true
        dynamic:
          druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)
            # 连接池的配置信息
            # 初始化大小,最小,最大
            initial-size: 5
            min-idle: 5
            maxActive: 20
            # 配置获取连接等待超时的时间r
            maxWait: 60000
            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # 配置一个连接在池中最小生存的时间,单位是毫秒
            minEvictableIdleTimeMillis: 300000
            validationQuery: SELECT 1 FROM DUAL
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            # 打开PSCache,并且指定每个连接上PSCache的大小
            poolPreparedStatements: true
            maxPoolPreparedStatementPerConnectionSize: 20
            # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
            filters: stat,wall,slf4j
            # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
            connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
          datasource:
            master:
              url: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
              username: root
              password: root
              driver-class-name: com.mysql.cj.jdbc.Driver
            second:
              url: jdbc:mysql://192.168.11.50:3306/commons_utils?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
              username: root
              password: root
              driver-class-name: com.mysql.cj.jdbc.Driver
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    3-1:加入依赖

            
            <dependency>
                <groupId>com.baomidougroupId>
                <artifactId>dynamic-datasource-spring-boot-starterartifactId>
                <version>3.2.0version>
            dependency>
    
            
            <dependency>
                <groupId>com.alibabagroupId>
                <artifactId>druid-spring-boot-starterartifactId>
                <version>1.2.6version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Druid连接池的自动配置类是DruidDataSourceAutoConfigure类上有一行注解

    @EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
    
    • 1

    @EnableConfigurationProperties注解的作用是:使配置文件中的配置生效并且映射到指定类的属性

    DruidStatProperties:指定的前缀是spring.datasource.druid,主要设置连接池的一些参数

    DataSourceProperties:指定的前缀是spring.datasource,主要设置url,username,password等信息

    3-2:DruidConfig 配置类

    package com.example.poi.config;
    
    import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
    import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
    import com.alibaba.druid.util.Utils;
    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    /**
     * @Description: DruidConfig配置类
     */
    @Configuration
    @AutoConfigureAfter(DruidDataSourceAutoConfigure.class)
    public class DruidConfig {
    
        /**
         * 带有广告的common.js全路径,druid-1.1.14
         */
        private static final String FILE_PATH = "support/http/resources/js/common.js";
        /**
         * 原始脚本,触发构建广告的语句
         */
        private static final String ORIGIN_JS = "this.buildFooter();";
        /**
         * 替换后的脚本
         */
        private static final String NEW_JS = "//this.buildFooter();";
    
        /**
         * 去除Druid监控页面的广告
         *
         * @param properties DruidStatProperties属性集合
         * @return {@link FilterRegistrationBean}
         */
        @Bean
        @ConditionalOnWebApplication
        @ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true")
        public FilterRegistrationBean<RemoveAdFilter> removeDruidAdFilter(
                DruidStatProperties properties) throws IOException {
            // 获取web监控页面的参数
            DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
            // 提取common.js的配置路径
            String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
            String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
            // 获取common.js
            String text = Utils.readFromResource(FILE_PATH);
            // 屏蔽 this.buildFooter(); 不构建广告
            final String newJs = text.replace(ORIGIN_JS, NEW_JS);
            FilterRegistrationBean<RemoveAdFilter> registration = new FilterRegistrationBean<>();
            registration.setFilter(new RemoveAdFilter(newJs));
            registration.addUrlPatterns(commonJsPattern);
            return registration;
        }
    
        /**
         * 删除druid的广告过滤器
         *
         * @author BBF
         */
        private class RemoveAdFilter implements Filter {
    
            private final String newJs;
    
            public RemoveAdFilter(String newJs) {
                this.newJs = newJs;
            }
    
            @Override
            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                    throws IOException, ServletException {
                chain.doFilter(request, response);
                // 重置缓冲区,响应头不会被重置
                response.resetBuffer();
                response.getWriter().write(newJs);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    4:配置动态数据源方法二,yml随意配置或者通过配置类生成数据库链接

    4-1:yml配置(记得配置数据库链接池)

    datasource:
      master:
        url: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
        username: root
        password: root
        driver-class-name: com.mysql.cj.jdbc.Driver
      second:
        url: jdbc:mysql://192.168.11.50:3306/commons_utils?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
        username: root
        password: root
        driver-class-name: com.mysql.cj.jdbc.Driver
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4-2:配置动态源数据类

    import javax.sql.DataSource;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
    
    @Configuration
    public class DatabaseConfig {
    
        @Value("${datasource.master.url}")
        private String dataSourceUrl;
    
        @Value("${datasource.master.username}")
        private String dataSourceUsername;
    
        @Value("${datasource.master.password}")
        private String dataSourcePassword;
    
        @Value("${datasource.master.driver-class-name}")
        private String dataSourceDriverClassName;
    
        @Value("${datasource.second.url}")
        private String dataSourceUrl2;
    
        @Value("${datasource.second.username}")
        private String dataSourceUsername2;
    
        @Value("${datasource.second.password}")
        private String dataSourcePassword2;
    
        @Value("${datasource.second.driver-class-name}")
        private String dataSourceDriverClassName2;
    
        public DataSource dataSource() {
            return  DataSourceBuilder.create()
                    .url(dataSourceUrl)
                    .username(dataSourceUsername)
                    .password(dataSourcePassword)
                    .driverClassName("com.mysql.cj.jdbc.Driver")
                    .build();
        }
        public DataSource dataSource2() {
            return DataSourceBuilder.create()
                    .url(dataSourceUrl2)
                    .username(dataSourceUsername2)
                    .password(dataSourcePassword2)
                    .driverClassName("com.mysql.cj.jdbc.Driver")
                    .build();
        }
    
        // 添加动态数据源
        @Bean
        public DynamicRoutingDataSource dynamicDataSource() {
            DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
            dynamicRoutingDataSource.addDataSource("master", dataSource());
            dynamicRoutingDataSource.addDataSource("two", dataSource2());
            return dynamicRoutingDataSource;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    4-3:在server服务层通过@DS调用

    import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
        @Override
        @DS("two")
        public List<EntityDemo> testSql(Page<EntityDemo> pageList, String id)  {
            List<EntityDemo> entityDemos = entityDemoMapper.testSql(pageList, id);
            DynamicDataSourceContextHolder.clear();
            return entityDemos;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4-4:可以在启动类观察动态数据源情况如下:run.getBean(DataSource.class).getConnection();

    @SpringBootApplication
    @MapperScan(basePackages = "com.example.poi.mapper")
    public class PoiApplication {
        public static void main(String[] args) {
            ConfigurableApplicationContext run = SpringApplication.run(PoiApplication.class, args);
            // 检查数据库连接是否正常
            try {
                // 获取DataSource bean,并调用getConnection()方法测试连接
                run.getBean(javax.sql.DataSource.class).getConnection();
                System.out.println("数据库连接正常!");
            } catch (Exception e) {
                System.err.println("数据库连接异常:" + e.getMessage());
                // 处理连接异常的逻辑
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    5:方法三配置动态数据源使,使用注解的方式(推荐使用)

    5-1:yml配置

    spring:
      datasource:
        master:
          jdbcUrl: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
        second:
          jdbcUrl: jdbc:mysql://192.168.11.50:3306/commons_utils?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
          username: root
          password: root
          driverClassName: com.mysql.cj.jdbc.Driver
        druid:
          #连接池初始化时创建的数据库连接数量
          initial-size: 10
          #连接池中保持最小的空闲连接数量。如果空闲连接数量少于这个值,连接池会创建新的连接来补充
          min-idle: 5
          #
          max-active: 80
          #配置获取链接等待超时的时间
          max-wait:
        type: com.alibaba.druid.pool.DruidDataSource
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    5-2:配置动态源数据类(在需要切换的地方使用@DS就可以),整合mybatis-plus的过程中,我们还需要创建动态数据源的SqlSessionFactory,如果我们想要实现动态数据源切换,则需要手动配置SqlSessionFactory,以便于它使用动态数据源,同理事务管理器也需要重新配置:

    @Configuration
    public class DatabaseConfig {
    
    
        @Bean("one")
        @ConfigurationProperties(prefix = "spring.datasource.master")
        public DataSource dataSource() {
            return DataSourceBuilder.create().build();
        }
    
        @Bean("two")
        @ConfigurationProperties(prefix = "spring.datasource.second")
        public DataSource dataSource2() {
            return DataSourceBuilder.create().build();
        }
    
        //添加动态数据源
        @Bean
        public DynamicRoutingDataSource dynamicDataSource(@Qualifier("one") DataSource dataSource, @Qualifier("two") DataSource dataSource2) {
            DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
            dynamicRoutingDataSource.addDataSource("master", dataSource);
            dynamicRoutingDataSource.addDataSource("two", dataSource2);
            return dynamicRoutingDataSource;
        }
    
    
       @Bean("sqlSessionFactory")
        public SqlSessionFactory sqlSessionFactoryBean(DynamicRoutingDataSource dynamicRoutingDataSource) throws Exception {
            //使用SqlSessionFactoryBean不可以正常使用 BaseMapper的MyBatis通用的CRUD
            //SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
            MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
            sessionFactory.setDataSource(dynamicRoutingDataSource);
            return sessionFactory.getObject();
    
        /**
         * 重写事务管理器,管理动态数据源
         */
        @Primary
        @Bean(value = "transactionManager")
        public PlatformTransactionManager annotationDrivenTransactionManager(DynamicRoutingDataSource dataSource) {
            return new DataSourceTransactionManager(dataSource);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    5-3:切换使用数据源

    在这里插入图片描述

    6:方法四配置动态数据源使用,使用注解的方式(推荐使用)

    6-1:添加注解和切面

    package com.example.poi.minds.annotation;
    
    import java.lang.annotation.*;
    
    /**
     * @Author xu
     * @create 2023/9/7 22
     */
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface MinDS {
    
        /**
         * groupName or specific database name or spring SPEL name.
         *
         * @return the database you want to switch
         */
        String value() default "";
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    package com.example.poi.minds.aop;
    
    import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
    import com.example.poi.config.DataSourceHolder;
    import com.example.poi.desensitization.annotation.SensitiveDecode;
    import com.example.poi.desensitization.annotation.SensitiveEncode;
    import com.example.poi.desensitization.utils.SensitiveInfoUtil;
    import com.example.poi.minds.annotation.MinDS;
    import lombok.extern.slf4j.Slf4j;
    import org.aopalliance.intercept.MethodInvocation;
    import org.apache.commons.lang.StringUtils;
    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.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    import java.util.List;
    
    /**
     * @Author xu
     * @create 2023/9/7 22
     */
    @Slf4j
    @Aspect
    @Component
    public class MinDSAspect {
    
        /**
         * 定义切点Pointcut
         */
        @Pointcut("@annotation(com.example.poi.minds.annotation.MinDS) ")
        public void dsPointCut() {
        }
    
        @Around("dsPointCut()")
        public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
            // 处理结果
    
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
    
            MinDS minDS = method.getAnnotation(MinDS.class);
            String value = minDS.value();
            if (StringUtils.isBlank(value)) {
                return null;
            }
            DataSourceHolder.setDataSource(value);
            try {
                return joinPoint.proceed();
            } finally {
                DataSourceHolder.clearDataSource();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    在这里插入图片描述

    6-2:动态数据源简单的说就是能够自由切换的数据源,Spring提供了一个抽象类AbstractRoutingDataSource,我们只需要extends ,并且重写determineCurrentLookupKey()即可determineCurrentLookupKey()的作用:返回需要切换的数据源的key,然后根据这个key获取对应的数据源信息

    package com.example.poi.config;
    
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
    
    /**
     * @Author xu
     * @create 2023/9/7 22
     */
    public class DynamicDataSource extends AbstractRoutingDataSource {
        /**
         * 返回需要使用的数据源key,将会按照这个key从Map中获取对应的数据源(切换)
         * @return
         */
        @Override
        protected Object determineCurrentLookupKey() {
            //从ThreadLocal中取出key
            return DataSourceHolder.getDataSource();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    6-3:单独封装一个类:DataSourceHolder,在多线程的情况下,数据源切换如何保证线程隔离呢?,我们不能这边切换了影响了其他线程的执行,这里我们便想到了ThreadLocal

    package com.example.poi.config;
    
    /**
     * @Author xu
     * @create 2023/9/7 20
     */
    /**
     * 线程安全类:使用ThreadLocal存储切换数据源后的KEY
     */
    public class DataSourceHolder {
        /**
         * 线程ThreadLocal
         */
        private static final ThreadLocal<String> dataSources = new InheritableThreadLocal();
    
        /**
         * 设置数据源
         * @param datasource
         */
        public static void setDataSource(String datasource) {
            dataSources.set(datasource);
        }
    
        /**
         * 获取数据源
         * @return
         */
        public static String getDataSource() {
            return dataSources.get();
        }
    
        /**
         * 清除数据源
         */
        public static void clearDataSource() {
            dataSources.remove();
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
  • 相关阅读:
    react151618刷新几次的问题
    计算机毕业设计(附源码)python在线学习交流平台
    5个网络问题,了解网络协议栈的哪些不为人知的八股文(来波千人福利)
    【CSS】基础使用,层级关系,选择器
    大数据技术分享 - 话题挑战跳大开团
    密集计算场景下的 JNI 实战
    第60节——使用redux-toolkit实战一个商品列表的增删查改
    php志愿者协会报名系统的设计与实现毕业设计源码201524
    PLAY TO EARN时代终结后 区块链游戏将为游戏行业带来真正的变革
    带权有向图最短路径之Dijkstra和Floyd
  • 原文地址:https://blog.csdn.net/qq_19891197/article/details/132697950