当前位置:   article > 正文

【SpringBoot】实现JdbcTemplate、Druid、Dynamic-Datasource的多数据源动态切换_jdbctemplate dynamic orcale多数据源切换

jdbctemplate dynamic orcale多数据源切换

一.前言

1.多数据源的使用场景

  1. 操作同一台服务器上不同的数据库,或者多台服务器上的相同或不相同数据库。
  2. 进行跨库操作、多数据源进行分离数据;
  3. 使得程序得以扩展,当一台或者部分服务器宕机,不影响整个应用的服务;

2.多数据源配置的思路

  1. 创建数据源DataSource ,指定使用哪个数据源(如Druid,DBCP,C3P0),并初始化数据源配置项,如连接url、驱动包、用户名、密码、连接数、超时时间等等。
  2. 创建会话工厂 sqlsessionFactory,并注入数据源以及要扫描mapper文件路径
  3. 创建事务管理器 transactionManager,并注入数据源
  4. 创建 sqlSessionTemplate 模板,并注入会话工厂sqlsessionFactory。

SpringBoot 默认支持如下数据源;

  1. 自动配置都在org.springframework.boot.autoconfigure.jdbc 包下。
  2. org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration 数据源配置类作用是根据逻辑判断之后,添加数据源
    • com.zaxxer.hikari.HikariDataSource (Spring Boot 2.0 以上,默认使用此数据源)
    • org.apache.tomcat.jdbc.pool.DataSource (Spring Boot 2.0.x 以下,默认使用此数据源)
    • org.apache.commons.dbcp2.BasicDataSource

二.JdbcTemplate的多数据源配置

HikariDataSource 号称 Java WEB 当前速度最快的数据源,相比于传统的 C3P0 、DBCP、Tomcat jdbc 等连接池更加优秀

1.默认数据源-HikariDataSource

  1. 全局配置文件application.ymlspring.datasource.* 下只配置账号、密码、数据库地址、连接驱动,默认使用的是 com.zaxxer.hikari.HikariDataSource 数据源
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.58.129:3307/horse?characterEncoding=UTF-8
    driver-class-name: com.mysql.jdbc.Driver
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 如果过是自定义数据源,比如 Druid,则可以使用spring.datasource.type指定
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.58.129:3307/horse?characterEncoding=UTF-8
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • Spring Boot 2.x 默认使用 com.zaxxer.hikari.HikariDataSource 数据源
  • Spring Boot 2.x一下 默认使用 org.apache.tomcat.jdbc.pool.DataSource 作为数据源

Spring Boot 2.+的默认连接池HikariCP详解

2.默认数据源数据库操作类JdbcTemplate

  1. 即使不使用第三方第数据库操作框架,如 MyBatis、Hibernate 、spring-data-jpa 等,Spring 本身也对 原生的 JDBC 做了轻量级的封装,即org.springframework.jdbc.core.JdbcTemplate

  2. JdbcTemplate 是 core 包的核心类,用于简化 JDBC 操作,还能避免一些常见的错误,如忘记关闭数据库连接。

  3. Spring Boot 不仅提供了默认的数据源HikariDataSource同时默认为JdbcTemplate注入数据源并初始化到Spring容器中,使用时只需自己注入即可使用

  4. JdbcTemplate 的自动配置原理是依赖 org.springframework.boot.autoconfigure.jdbc 包下的 org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration

3.使用步骤

3.1.修改配置文件application.yml

配置多个数据源

spring:
  datasource:
    master:
       	# 基本属性 url、user、password 
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
        username: root
        password: 123456
    slave:
       	# 基本属性 url、user、password 
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/slave_db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
        username: root
        password: 123456
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

数据源连接配置2.x和1.x的配置项是有区别的:

  • 2.x使用spring.datasource.master.jdbc-url
  • 1.x版本使用spring.datasource.master.url

如果你在配置的时候发生了这个报错java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.,那么就是这个配置项的问题。

3.2.JdbcTemplate数据源配置类
@Configuration
public class DataSourceConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.master")
    @Primary
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public JdbcTemplate masterJdbcTemplate(@Qualifier("masterDataSource") DataSource primaryDataSource) {
        return new JdbcTemplate(primaryDataSource);
    }

    @Bean
    public JdbcTemplate slaveJdbcTemplate(@Qualifier("slaveDataSource") DataSource secondaryDataSource) {
        return new JdbcTemplate(secondaryDataSource);
    }
}
  • 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
  1. 前两个Bean是数据源的创建,通过**@ConfigurationProperties** 可以知道这两个数据源分别加载了spring.datasource.master.*spring.datasource.slave.*的配置然后初始化数据源。
  2. @Primary注解指定了主数据源,就是当我们不特别指定哪个数据源的时候,就会使用这个Bean
    后两个Bean是每个数据源对应的JdbcTemplate。可以看到这两个JdbcTemplate创建的时候,分别注入了masterDataSource数据源slaveDataSource数据源
3.2.测试

JdbcTemplate 的CRUD伪代码

@RunWith(SpringRunner.class)
@SpringBootTest
public class Chapter37ApplicationTests {
    @Autowired
    protected JdbcTemplate masterJdbcTemplate;

    @Autowired
    protected JdbcTemplate slaveJdbcTemplate;

    @Before
    public void setUp() {
        primaryJdbcTemplate.update("DELETE  FROM  USER ");
        secondaryJdbcTemplate.update("DELETE  FROM  USER ");
    }

    @Test
    public void test() throws Exception {
        // 往第一个数据源中插入 2 条数据
        masterJdbcTemplate.update("insert into user(name,age) values(?, ?)", "aaa", 20);
        masterJdbcTemplate.update("insert into user(name,age) values(?, ?)", "bbb", 30);

        // 往第二个数据源中插入 1 条数据,若插入的是第一个数据源,则会主键冲突报错
        slaveJdbcTemplate.update("insert into user(name,age) values(?, ?)", "ccc", 20);

        // 查一下第一个数据源中是否有 2 条数据,验证插入是否成功
        Assert.assertEquals("2", masterJdbcTemplate.queryForObject("select count(1) from user", String.class));

        // 查一下第一个数据源中是否有 1 条数据,验证插入是否成功
        Assert.assertEquals("1", masterJdbcTemplate.queryForObject("select count(1) from user", String.class));
    }

    /**查询*/
    @Test
    public void userList() {
        /**
         * List 中的1个 Map 对应数据库的 1行数据
         * Map 中的 key 对应数据库的字段名,value 对应数据库的字段值
         */
        List<Map<String, Object>> mapList = masterJdbcTemplate.queryForList("SELECT * FROM phone");
    }

	//--------update 方法可以做查询以外的 增加、修改、删除操作---------------
     /**新增*/
    @Test
    public void savePhone() {
        String sql = "INSERT INTO phone(number,region) VALUES (?,?)";
        Object[] objects = new Object[2];
        objects[0] = "18673886425";
        objects[1] = "湖南";
        masterJdbcTemplate.update(sql, objects);
    }

     /**修改*/
    @Test
    public void updatePhone() {
        String sql = "UPDATE phone SET number=? WHERE pid=?";
        Object[] objects = new Object[2];
        objects[0] = "18666668888";
        objects[1] = "1";
        masterJdbcTemplate.update(sql, objects);
    }
    
     /**删除*/
    @Test
    public void deletePhone() {
        String sql = "DELETE FROM phone WHERE number=?";
        Object[] objects = new Object[1];
        objects[0] = "18673886425";
        masterJdbcTemplate.update(sql, objects);
    }
}
  • 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

三.Spring-Data-JPA的多数据源配置(了解即可)

1.引入依赖

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.修改配置文件application.yml

配置多个数据源

spring:
  datasource:
    master:
       	# 基本属性 url、user、password 
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
        username: root
        password: 123456
    slave:
       	# 基本属性 url、user、password 
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/slave_db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
        username: root
        password: 123456
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

3.Jpa数据源配置类

有几个数据源就写几个配置类

master数据源的JPA配置:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef="entityManagerFactoryMaster",
        transactionManagerRef="transactionManagerMaster",
        basePackages= { "com.oyjp.master.repository" }) //设置Repository所在位置
public class MasterConfig {

    @Autowired
    @Qualifier("masterDataSource")
    private DataSource masterDataSource;

    @Autowired
    private JpaProperties jpaProperties;
    @Autowired
    private HibernateProperties hibernateProperties;

    private Map<String, Object> getVendorProperties() {
        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
    }

    @Primary
    @Bean(name = "entityManagerMaster")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryMaster(builder).getObject().createEntityManager();
    }

    @Primary
    @Bean(name = "entityManagerFactoryMaster")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryMaster(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(masterDataSource)
                .packages("com.oyjp.master.entity") //设置实体类所在位置
                .persistenceUnit("masterPersistenceUnit")
                .properties(getVendorProperties())
                .build();
    }

    @Primary
    @Bean(name = "transactionManagerMaster")
    public PlatformTransactionManager transactionManagerMaster(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryMaster(builder).getObject());
    }
}
  • 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

slave数据源的JPA配置:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef="entityManagerFactorySlave",
        transactionManagerRef="transactionManagerSlave",
        basePackages= { "com.oyjp.slave.repository" }) //设置Repository所在位置
public class SecondaryConfig {

    @Autowired
    @Qualifier("slaveDataSource")
    private DataSource slaveDataSource;

    @Autowired
    private JpaProperties jpaProperties;
    @Autowired
    private HibernateProperties hibernateProperties;

    private Map<String, Object> getVendorProperties() {
        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
    }

    @Bean(name = "entityManagerSlave")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactorySlave(builder).getObject().createEntityManager();
    }

    @Bean(name = "entityManagerFactorySlave")
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySlave (EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(slaveDataSource)
                .packages("com.oyjp.slave.entity") //设置实体类所在位置
                .persistenceUnit("secondaryPersistenceUnit")
                .properties(getVendorProperties())
                .build();
    }

    @Bean(name = "transactionManagerSlave")
    PlatformTransactionManager transactionManagerSlave(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactorySlave(builder).getObject());
    }
}
  • 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

说明与注意:

  • 在使用JPA的时候,需要为不同的数据源创建不同的package来存放对应的Entity和Repository,以便于配置类的分区扫描
  • 类名上的注解@EnableJpaRepositories指定Repository的所在位置
  • LocalContainerEntityManagerFactoryBean创建的时候,指定Entity所在的位置

主要注意在互相注入时候,不同数据源不同配置的命名,基本就没有什么大问题了

4.测试

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class Chapter38ApplicationTests {

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private MessageRepository messageRepository;

    @Test
    public void test() throws Exception {
        userRepository.save(new User("aaa", 10));
        userRepository.save(new User("bbb", 20));
        userRepository.save(new User("ccc", 30));
        userRepository.save(new User("ddd", 40));
        userRepository.save(new User("eee", 50));

        Assert.assertEquals(5, userRepository.findAll().size());

        messageRepository.save(new Message("o1", "aaaaaaaaaa"));
        messageRepository.save(new Message("o2", "bbbbbbbbbb"));
        messageRepository.save(new Message("o3", "cccccccccc"));

        Assert.assertEquals(3, messageRepository.findAll().size());
    }
}
  • 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

四.Durid+Mybatis的多数据源配置

1.引入依赖

在 pom.xml 文件中添加上 Druid 数据源依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>www.test.com</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>horse</name>
    <description>Demo project for Spring Boot</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/>
        <!-- lookup parent from repository -->
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
 
    <dependencies>
        <!-- 引入Spring封装的jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
 
        <!-- 引入web项目启动模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
 
        <!-- 引入mysql数据库连接驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        
         <!-- Spring Boot Mybatis 依赖 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        
        <!-- 引入 Druid 数据源依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.9</version>
        </dependency>
 
        <!-- 引入Spring Boot 测试模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <build>
        <plugins> </plugins>
        <resources>
            <!--src/main/resources下面所有文件打包-->
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
            <!--src/main/java下面存在xml文件也打包进去,解决 mapper与xml映射文件处于同级目录下却无法找到文件-->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>
  • 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
  • 86

2.修改配置文件application.yml

配置多个数据源

spring:
  datasource:
    druid:
      master:
       	# 基本属性 url、user、password 
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
        username: root
        password: 123456
        #  通过connectProperties属性来打开mergeSql功能;慢SQL记录
        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
         # 配置监控统计拦截的filters
        filters: stat,wall,log4j2
        # 配置初始化大小、最小、最大 
        initial-size: 5
        max-active: 20
        max-pool-prepared-statement-per-connection-size: 20
        # 配置获取连接等待超时的时间
        max-wait: 60000
        min-idle: 5
        pool-prepared-statements: true
        test-on-borrow: false
        test-on-return: false
        test-while-idle: true
        type: com.alibaba.druid.pool.DruidDataSource
        validation-query: SELECT 1 FROM DUAL
        validation-query-timeout: 30000
      slave:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/slave_db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
        username: root
        password: 123456
        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
        filters: stat,wall,log4j2
        initial-size: 5
        max-active: 20
        max-pool-prepared-statement-per-connection-size: 20
        max-wait: 60000
        min-idle: 5
        pool-prepared-statements: true
        test-on-borrow: false
        test-on-return: false
        test-while-idle: true
        type: com.alibaba.druid.pool.DruidDataSource
        validation-query: SELECT 1 FROM DUAL
        validation-query-timeout: 30000
  • 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

3.Druid监控配置类

import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
 
@Configuration
public class DruidConfig {
    /**
     * 配置Druid监控
     * 后台管理Servlet
     * @return
     */
    @Bean
    public ServletRegistrationBean statViewServlet(){
    	 //注册服务
        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        Map<String,String> initParams = new HashMap<>();
        //这是配置的druid监控的登录密码
        initParams.put("loginUsername","admin");
        initParams.put("loginPassword","123456");
        // 白名单(为空表示,所有的都可以访问,多个IP的时候用逗号隔开)默认就是允许所有访问
        initParams.put("allow", "127.0.0.1");
        // IP黑名单 (存在共同时,deny优先于allow) (黑白名单就是如果是黑名单,那么该ip无法登陆该可视化界面)
         initParams.put("deny", "127.0.0.2");
       // 是否能够重置数据.
        initParams.put("resetEnable", "false");
        bean.setInitParameters(initParams);
        return bean;
    }
    /**
     * 配置web监控的filter
     * @return
     */
    @Bean
    public FilterRegistrationBean webStatFilter(){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());
        // 添加过滤规则
        bean.setUrlPatterns(Arrays.asList("/*"));
        
         // 添加过滤规则
        Map<String,String> initParams = new HashMap<>();
        // 添加不需要忽略的格式信息
        initParams.put("exclusions","/static/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");//过滤掉需要监控的文件
        initParams.put("profileEnable", "true");
        initParams.put("principalCookieName", "USER_COOKIE");
        initParams.put("principalSessionName", "USER_SESSION");
        initParams.put("DruidWebStatFilter", "/*");

        bean.setInitParameters(initParams);
        return  bean;
    }
}
  • 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

4.配置Druid监控平台的Spring监控

如果访问Druid监控平台的Spring监控没有数据
在这里插入图片描述

import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
 
/**
 * spring监控配置
 * @author
 */
@Configuration
public class SpringDaoMethodAspect {
	
	@Bean
	public DruidStatInterceptor druidStatInterceptor() {
		DruidStatInterceptor dsInterceptor = new DruidStatInterceptor();
		return dsInterceptor;
	}
	
	@Bean
	@Scope("prototype")
	public JdkRegexpMethodPointcut druidStatPointcut() {
		JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
		pointcut.setPattern("com.yadu.example.demo.mapper.*");
		return pointcut;
	}
	
	@Bean
	public DefaultPointcutAdvisor druidStatAdvisor(DruidStatInterceptor druidStatInterceptor, JdkRegexpMethodPointcut druidStatPointcut) {
		DefaultPointcutAdvisor defaultPointAdvisor = new DefaultPointcutAdvisor();
		defaultPointAdvisor.setPointcut(druidStatPointcut);
		defaultPointAdvisor.setAdvice(druidStatInterceptor);
		return defaultPointAdvisor;
	}
}
  • 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

5.Druid数据源配置类

(有几个数据源就写几个配置类)

  • 注意:数据源是在在第一次连接数据库的时候进行初始化的

主数据源

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 
import javax.sql.DataSource;
 
@Configuration
@MapperScan(
	basePackages = "com.yadu.example.demo.mapper.master", 
	sqlSessionTemplateRef= "masterSqlSessionTemplate",
	sqlSessionFactoryRef="masterSqlSessionFactory")
public class MasterDataSourceConfiguration {
 
	 /**创建数据源*/
    @Bean(name = "masterDataSource")
    @Primary   //表示这个数据源是默认数据源, 这个注解必须要加,因为不加的话spring将分不清楚那个为主数据源(默认数据源)
    //将spring.datasource.druid.master开头的配置映射成对象DruidDataSource
    //也可以使用 @Value("${spring.datasource.druid.master.username:#{null}}") 指定属性映射
    @ConfigurationProperties(prefix = "spring.datasource.druid.master")
    public DataSource dataSource() {
        return  new DruidDataSource();
    }
    
 	/**创建SessionFactory*/
    @Bean(name = "masterSqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        // mapper的xml形式文件位置必须要配置,不然将报错:no statement (这种错误也可能是mapper的xml中,namespace与项目的路径不一致导致)
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapping/*.xml"));
        return bean.getObject();
    }
    
	 /**创建事务管理器*/
    @Bean(name = "masterTransactionManager")
     @Primary
    public DataSourceTransactionManager transactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
    
	 /**创建SqlSessionTemplate*/
    @Bean(name = "masterSqlSessionTemplate")
     @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory)
            throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
  • 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
  • 配置类上使用@MapperScan注解来指定当前数据源下定义的Entity和Mapper的包路径另外需要指定sqlSessionFactory和sqlSessionTemplate,这两个具体实现在该配置类中类中初始化。
  • @Primary 这个 Bean 如果在多个相同类型的 Bean 时,优先使用当前Bean。「多数据源配置的时候注意,必须要有一个主数据源,用 @Primary 标志该 Bean」
  • @Value 获取全局配置文件application.properties 的 属性配置,并自动装配

从数据源

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 
import javax.sql.DataSource;
 
 
@Configuration
@MapperScan(
	basePackages = "com.yadu.example.demo.mapper.slave", 
	sqlSessionFactoryRef= "slaveSqlSessionTemplate",
	sqlSessionFactoryRef="slaveSqlSessionFactory")
public class SlaverDataSourceConfiguration {
 
    @Bean(name = "slaveDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.druid.slave")
    public DataSource dataSource() {
        return  new DruidDataSource();
    }
 
    @Bean(name = "slaveSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        // 注入数据源
        bean.setDataSource(dataSource);
         // mapper的xml形式文件位置必须要配置,不然将报错:no statement (这种错误也可能是mapper的xml中,namespace与项目的路径不一致导致)
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapping/*.xml"));
        return bean.getObject();
    }
 
    @Bean(name = "slaveTransactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier("slaveDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
 
    @Bean(name = "slaveSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("slaveSqlSessionFactory") SqlSessionFactory sqlSessionFactory)
            throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
  • 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

SessionFactory初始化时还可以指定配置文件的路径、mapper文件路径、实体类别名映射
配置如下:

@Configuration
public class SessionFactoryConfiguration {

    // mybatis-config.xml配置文件的路径
    @Value("${mybatis_config_file}")
    private String mybatisConfigFilePath;

    // mybatis mapper文件所在路径
    @Value("${mapper_path}")
    private String mapperPath;

    // 实体类所在的package
    @Value("${entity_package}")
    private String entityPackage;

    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;

    @Bean(name="sqlSessionFactory")
    public SqlSessionFactoryBean createSqlSessionFactoryBean() throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        // 扫描mybatis配置文件
        sqlSessionFactoryBean.setConfigLocation(new ClassPathResource(mybatisConfigFilePath));
        // 扫描相关mapper文件
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        String packageSearchPath = PathMatchingResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + mapperPath;
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources(packageSearchPath));
        // 调用dataSource
        sqlSessionFactoryBean.setDataSource(dataSource);
        // 映射实体类
        sqlSessionFactoryBean.setTypeAliasesPackage(entityPackage);
        return sqlSessionFactoryBean;
    }

  • 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

6.启动类去除默认数据源配置

DruidDataSourceAutoConfigure会注入一个DataSourceWrapper,其会在原生的spring.datasource下找 url, username, password 等。

排除方式有两种,一种是将上述配置文件排除

spring:
  autoconfigure:
    #去除durid配置
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
  • 1
  • 2
  • 3
  • 4

还有一种可以在项目启动类排除

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,DruidDataSourceAutoConfigure.class})
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这个时候,在yml文件当中就不能像单个数据源的时那样配置mapper的位置了:

mybatis:
  mapper-locations: classpath:mapper/*.xml
  • 1
  • 2

7.sql监控访问

http://localhost:9001/druid/datasource.html

  • 往下滑可以发现初始化了两个数据库,需要注意的是 数据源是在第一次请求数据库连接的时候初始化的
    在这里插入图片描述

在这里插入图片描述

8.补充(去除Druid广告)

访问sql监控的时候,你可能会看到阿里巴巴的广告,如果想去掉,有两种方式

  1. 修改druid中的js源码,可参考
  2. 增加配置文件

五.Druid+MybatisPlus+Dynamic-Datasource多数据源配置

  • dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。支持 Jdk 1.7+, SpringBoot 1.5.x 和 2.x.x

1.特性

  1. 支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。
  2. 支持数据库敏感配置信息 加密 ENC()
  3. 支持每个数据库独立初始化表结构schema和数据库database。
  4. 支持 自定义注解 ,需继承DS(3.2.0+)。
  5. 提供对Druid,Mybatis-Plus,P6sy,Jndi的快速集成。
  6. 简化Druid和HikariCp配置,提供 全局参数配置 。配置一次,全局通用。
  7. 提供 自定义数据源来源 方案。
  8. 提供项目启动后 动态增加移除数据源 方案。
  9. 提供Mybatis环境下的 纯读写分离 方案。
  10. 提供使用 spel动态参数 解析数据源方案。内置spel,session,header,支持自定义。
  11. 支持 多层数据源嵌套切换 。(ServiceA >>> ServiceB >>> ServiceC)。
  12. 提供对shiro,sharding-jdbc,quartz等第三方库集成的方案
  13. 提供 基于seata的分布式事务方案。 附:不支持原生spring事务。
  14. 提供 本地多数据源事务方案。 附:不支持原生spring事务。

2.约定

  1. 本框架只做 切换数据源 这件核心的事情,并不限制你的具体操作,切换了数据源可以做任何CRUD。
  2. 配置文件所有以下划线 _ 分割的数据源前缀即为组的名称,相同组名称的数据源会放在一个组下。
  3. 切换数据源可以是组名,也可以是具体数据源名称。组名则切换时采用负载均衡算法切换。
  4. 默认的数据源名称为 master ,你可以通过 spring.datasource.dynamic.primary 修改。
  5. 方法上的注解优先于类上注解
  6. 强烈建议只在service的类方法上添加注解不建议在mapper上添加注解。

3.快速入门

3.1.引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>www.test.com</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>horse</name>
    <description>Demo project for Spring Boot</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/>
        <!-- lookup parent from repository -->
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
 
    <dependencies>
        <!-- 引入Spring封装的jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        
        <!-- 引入web项目启动模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
 
        <!--关键0: 引入mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--关键1: mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>

        <!--关键2: 引入多数据源依赖dynamic-datasource-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.3.1</version>
        </dependency>

        <!--关键3: 引入连接池druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
            <scope>compile</scope>
        </dependency>
 
        <!-- 引入Spring Boot 测试模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <build>
        <plugins> </plugins>
        <resources>
            <!--src/main/resources下面所有文件打包-->
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
            <!--src/main/java下面存在xml文件也打包进去,解决 mapper与xml映射文件处于同级目录下却无法找到文件-->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>
  • 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
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 关键是引入了mybatis-plus、dynamic-datasource、druid依赖
3.2.修改配置文件application.yml

配置多个数据源

3.2.1.dynamic-datasource默认配置解析
spring:
  datasource:
    # druid登陆配置,登录地址为 ip:port/druid
    druid:
      stat-view-servlet:
        enabled: true
        loginUsername: xxx #登录名
        loginPassword: xxx #登录密码
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master  #指定默认数据源(命名必须为master开头否则会报错)
      strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.
      datasource:
        master:
          url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
        slave_1:
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        slave_2:
          url: ENC(xxxxx) # 内置加密,使用请查看详细文档
          username: ENC(xxxxx)
          password: ENC(xxxxx)
          driver-class-name: com.mysql.jdbc.Driver
          schema: db/schema.sql # 配置则生效,自动初始化表结构
          data: db/data.sql # 配置则生效,自动初始化数据
          continue-on-error: true # 默认true,初始化失败是否继续
          separator: ";" # sql默认分号分隔符
          
       #......省略
       #以上会配置一个默认库master,一个组slave下有两个子库slave_1,slave_2
  • 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
3.2.2.多数据源模式
# 多主多从                      纯粹多库(记得设置primary)                   混合配置
spring:                               spring:                               spring:
  datasource:                           datasource:                           datasource:
    dynamic:                              dynamic:                              dynamic:
      datasource:                           datasource:                           datasource:
        master_1:                             mysql:                                master:
        master_2:                             oracle:                               slave_1:
        slave_1:                              sqlserver:                            slave_2:
        slave_2:                              postgresql:                           oracle_1:
        slave_3:                              h2:                                   oracle_2:
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
3.2.3.当前配置
###MySQL druid多数据源配置(纯粹多库)###
spring:
  datasource:
    # druid登陆配置,登录地址为 ip:port/druid
    druid:
      stat-view-servlet:
        enabled: true
        loginUsername: admin #登录名
        loginPassword: 123456 #登录密码
  autoconfigure:
    #去除durid配置
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
  datasource:
    dynamic:
      #指定默认数据源(必须配置,且名字必须为master开头否则会报错)
      primary: master
      #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候回抛出异常,不启动会使用默认数据源.
      strict: false
      datasource:
        #db01库
        master:
          driver-class-name: com.mysql.jdbc.Driver
          password: root
          url: jdbc:mysql://127.0.0.1:3306/db01?serverTimezone=GMT&useSSL=false
          username: root
        #db02库
        db02:
          driver-class-name: com.mysql.cj.jdbc.Driver
          password: root
          url: jdbc:mysql://127.0.0.1:3306/db02?serverTimezone=GMT&useSSL=false
          username: toot
      #数据源基础配置
      druid:
        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
        # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
        filters: stat,wall,slf4j
        initial-size: 5
        max-active: 20
        max-pool-prepared-statement-per-connection-size: 20
        # 配置获取连接等待超时的时间
        max-wait: 6000
        # 配置一个连接在池中最小生存的时间,单位是毫秒
        min-evictable-idle-time-millis: 300000
        min-idle: 5
        pool-prepared-statements: true
        test-on-borrow: false
        test-on-return: false
        test-while-idle: true
        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
        time-between-eviction-runs-millis: 60000
        validation-query: 'SELECT 1 FROM DUAL '
  • 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
3.3.编写Mapper层

如: 可以直接编写Mapper接口 或 继承BaseMapper <T> 接口, 就可以直接使用MybatisPlus内置的mapper层方法了

public interface UserMapper extends BaseMapper<User> {}
  • 1
3.4.使用 @DS 切换数据源
注解结果
没有@DS默认数据源
@DS(“dsName”)dsName可以为组名也可以为具体某个库的名称
  • @DS(“”)括号内即是application.properties中配置的数据源名称,不加注解默认是访问主库master通过spring.datasource.dynamic.primary设置,可加在service方法上,也可加在mapper方法上。. 强烈建议只在service的类方法上添加注解不建议在mapper上添加注解。
  • @DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解

伪代码: 在service层调用这个mapper的方法,并且在在方法上添加@DS 验证效果。

@Service
@DS("slave")
public class UserServiceImpl implements UserService {
 
  @Autowired
  private JdbcTemplate jdbcTemplate;  
  
  public List<Map<String, Object>> selectAll() {
    return  jdbcTemplate.queryForList("select * from user");
  }
  
  @Override
  @DS("master")
  public List<Map<String, Object>> selectByCondition() {
    return  jdbcTemplate.queryForList("select * from user where age >10");
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
@DS("slave")
public interface UserMapper {
 
  @Insert("INSERT INTO user (name,age) values (#{name},#{age})")
  boolean addUser(@Param("name") String name, @Param("age") Integer age);
 
  @Update("UPDATE user set name=#{name}, age=#{age} where id =#{id}")
  boolean updateUser(@Param("id") Integer id, @Param("name") String name, @Param("age") Integer age);
 
  @Delete("DELETE from user where id =#{id}")
  boolean deleteUser(@Param("id") Integer id);
 
  @Select("SELECT * FROM user")
  @DS("master")
  List<User> selectAll();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
3.5.启动类排除原生Druid的配置类
  1. 在启动类配置@MapperScan注解扫描Mapper层

  2. 在启动类@SpringBootApplication注解中,排除原生Druid的配置类。因为项目默认连接Druid的原生配置的mysql服务。

  • 有两种方式
  • DruidDataSourceAutoConfigure会注入一个DataSourceWrapper,其会在原生的spring.datasource下找 url, username, password 等。
//1.@MapperScan扫描Mapper层
@MapperScan("com.egos.web.*.mapper")
//2.排除原生Druid的配置类
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,DruidDataSourceAutoConfigure.class})
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
3.6.通过durid查看监控

访问 ip:port/druid,登录密码为
在这里插入图片描述

在这里插入图片描述

MyBatis-Plus官网文档
MyBatis-Plus-dynamic-datasource官方文档
dynamic-datasource-spring-boot-starter读写分离分析

在这里插入图片描述

添加微信,一起讨论Java、健身、养猫知识,哈哈哈
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/55962
推荐阅读
相关标签
  

闽ICP备14008679号