成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring Boot + MyBatis-Plus 實現 MySQL 主從復制動態數據源切換

開發 前端
AbstractRoutingDataSource 是 Spring Framework 提供的一個抽象數據源類,用于實現動態數據源切換。它允許應用程序在運行時動態地切換到不同的數據源,從而支持多數據源的場景,比如數據庫讀寫分離、主從復制等

MySQL 主從復制是一種常見的數據庫架構,它可以提高數據庫的性能和可用性。動態數據源切換則可以根據業務需求,在不同場景下使用不同的數據源,比如在讀多寫少的場景下,可以通過切換到從庫來分擔主庫的壓力。

在本文中,我們將介紹如何在 Spring Boot 中實現 MySQL 主從復制和動態數據源切換,使用 MyBatis-Plus 進行數據庫操作

#代碼地址
https://github.com/bangbangzhou/spring-boot-dynamic-master-slave.git

今日內容介紹,大約花費19分鐘

圖片圖片

那么接下來我們開始項目實現,項目結構如下

圖片圖片

1.引入依賴

在項目的的pom.xml文件中引入Spring Boot和MyBatis-Plus的相關依賴

<?xml versinotallow="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>

    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.7.15</version>
    </parent>

    <groupId>com.zbbmeta</groupId>
    <artifactId>spring-boot-dynamic-master-slave</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3</version>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.20</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2. 配置數據源

在application.yml文件中配置主從數據源信息。注意這里我們要搭建主從數據庫,只是在一個mysql實例中創建兩個庫,里面存在相同表

server:
  port: 8082

spring:
  datasource:
    master:
      username: root
      password: root
      url: jdbc:mysql://localhost:3306/shiro_db?useUnicode=true&characterEncoding=utf8
      driver-class-name: com.mysql.cj.jdbc.Driver
    slave:
      username: root
      password: root
      url: jdbc:mysql://localhost:3306/backend_db?useUnicode=true&characterEncoding=utf8
      driver-class-name: com.mysql.cj.jdbc.Driver


mybatis-plus:
  mapper-locations: classpath*:/mapper/**/*.xml

3. 創建DatabaseType 枚舉類型

創建DatabaseType 枚舉類型,用于切換數據源時,確定連接的是哪個數據源

在com.zbbmeta.config包下創建DatabaseType枚舉類型

// 定義一個枚舉類型 DatabaseType,表示系統中的數據庫類型
public enum DatabaseType {
    MASTER,  // 主數據庫類型
    SLAVE    // 從數據庫類型
}

4. 配置數據源上下文

在com.zbbmeta.holder包下創建一個DataSourceContextHolder類用于保存和獲取當前線程使用的數據源類型

public class DatabaseContextHolder {

    private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<>();

    public static void setDatabaseType(DatabaseType databaseType) {
        contextHolder.set(databaseType);
    }

    public static DatabaseType getDatabaseType() {
        return contextHolder.get();
    }

    public static void clearDatabaseType() {
        contextHolder.remove();
    }
}

5. 配置動態數據源

我們創建了一個 DynamicDataSource 類,繼承 AbstractRoutingDataSource,用于實現動態數據源的切換。

AbstractRoutingDataSource 是 Spring Framework 提供的一個抽象數據源類,用于實現動態數據源切換。它允許應用程序在運行時動態地切換到不同的數據源,從而支持多數據源的場景,比如數據庫讀寫分離、主從復制等

AbstractRoutingDataSource介紹:

  • 動態數據源切換:AbstractRoutingDataSource 的核心思想是根據某個鍵值(lookup key)來決定使用哪個具體的數據源。這個鍵值是通過 determineCurrentLookupKey() 方法提供
  • 抽象類:AbstractRoutingDataSource 是一個抽象類,它提供了模板方法 determineCurrentLookupKey(),需要由子類實現
  • 實現 javax.sql.DataSource 接口:AbstractRoutingDataSource 實現了 javax.sql.DataSource 接口,因此可以像常規數據源一樣被用于與數據庫的交互。
  • 在 Spring 配置中使用:在 Spring 的配置中,我們可以將 AbstractRoutingDataSource 配置為數據源 bean,并將真實的數據源作為其目標數據源。在需要切換數據源的時候,調用 determineCurrentLookupKey() 方法,它將返回用于切換數據源的鍵值。

在com.zbbmeta.config包下創建DynamicDataSource類

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSourceType();
    }
}

DynamicDataSource類中重寫determineCurrentLookupKey()方法:在這個方法中,我們通過調用 DataSourceContextHolder.getDataSourceType() 來獲取當前線程持有的數據源類型。這個方法的返回值將被用作數據源的 lookup key,從而實現動態切換。

6. 添加DataSource注解類

在·com.zbbmeta.annotation包下創建DataSource注解類,這是一個自定義注解,用于標記在類或方法上,以指定數據源的類型。下面是對這段代碼的注解說明

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {

    DatabaseType type() default DatabaseType.SLAVE;

}

注解說明:

  • @interface DataSource:這是一個注解的聲明,用于創建名為 DataSource 的自定義注解。
  • @Target({ElementType.METHOD, ElementType.TYPE}):@Target 注解表示此注解可以用于類和方法。在這里,DataSource 注解可以標注在類和方法上。
  • @Retention(RetentionPolicy.RUNTIME):@Retention 注解表示這個注解的生命周期,即在運行時仍然可用。這是因為我們希望在運行時通過反射獲取注解信息。
  • DatabaseType type() default DatabaseType.SLAVE:這是 DataSource 注解的一個成員變量。它是一個枚舉類型的變量,表示數據庫類型,默認值為 SLAVE。通過這個成員變量,我們可以在使用 DataSource 注解時指定使用的數據源類型

7. 配置數據源切換切面

在com.zbbmeta.aspect包下創建一個切面類DataSourceAspect,用于在執行數據庫操作前動態切換數據源。

@Aspect
@Component
@EnableAspectJAutoProxy
public class DataSourceAspect {
// 定義切點,匹配使用了 @DataSource 注解的方法
    @Pointcut("@annotation(com.zbbmeta.annotation.DataSource)")
    public void dataSourcePointCut() {}

    // 環繞通知,在方法執行前后切換數據源
    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();

        // 獲取方法上的 @DataSource 注解
        DataSource dataSource = method.getAnnotation(DataSource.class);
        if (dataSource != null) {
            // 切換數據源類型
            DatabaseContextHolder.setDatabaseType(dataSource.type());
        }

        try {
            // 執行目標方法
            return point.proceed();
        } finally {
            // 清除數據源類型,確保線程安全
            DatabaseContextHolder.clearDatabaseType();
        }
    }
}

8. 創建DataSourceConfig

在com.zbbmeta.config包下創建DataSourceConfig,用于配置主從兩個數據源

@Configuration
@Data
public class DataSourceConfig {
    @Value("${spring.datasource.master.url}")
    private String dbUrl;
    @Value("${spring.datasource.master.username}")
    private String username;
    @Value("${spring.datasource.master.password}")
    private String password;
    @Value("${spring.datasource.master.driver-class-name}")
    private String driverClassName;


    @Value("${spring.datasource.slave.url}")
    private String slaveDbUrl;
    @Value("${spring.datasource.slave.username}")
    private String slaveUsername;
    @Value("${spring.datasource.slave.password}")
    private String slavePassword;
    @Value("${spring.datasource.slave.driver-class-name}")
    private String slaveDriverClassName;


    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create()
                .driverClassName(driverClassName)
                .url(dbUrl)
                .username(username)
                .password(password)
                .build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {

        return DataSourceBuilder.create()
                .driverClassName(slaveDriverClassName)
                .url(slaveDbUrl)
                .username(slaveUsername)
                .password(slavePassword)
                .build();

    }
}

9 創建DataSourceConfig

在com.zbbmeta.config包下創建DynamicDataSourceConfig類中配置MyBatis-Plus的相關內容。

@Configuration
@MapperScan("com.zbbmeta.mapper")
public class DynamicDataSourceConfig {
    @Autowired
    private DataSource masterDataSource;

    @Autowired
    private DataSource slaveDataSource;

    // 配置動態數據源
    @Bean
    @Primary
    public DataSource dynamicDataSource() {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DatabaseType.MASTER, masterDataSource);
        targetDataSources.put(DatabaseType.SLAVE, slaveDataSource);

        DynamicRoutingDataSource dynamicDataSource = new DynamicRoutingDataSource();
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(masterDataSource); // 設置默認數據源
        return dynamicDataSource;
    }

    // 配置 MyBatis 的 SqlSessionFactory
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dynamicDataSource) throws Exception {
        MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dynamicDataSource);

        // 設置要掃描的 mapper 接口和 XML 文件路徑
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        sessionFactoryBean.setTypeAliasesPackage("com.zbbmeta.entity");  // 設置實體類包路徑

        return sessionFactoryBean.getObject();
    }

    // 配置 MyBatis 的 SqlSessionTemplate
    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

10. 測試

使用MybatisX生成代碼,并且創建com.zbbmeta.controller包下創建TutorialController類,并且在需要切換數據源的方法上使用 @DataSource 注解,切面將根據該注解的配置在方法執行前后進行數據源切換。

圖片圖片

圖片圖片

@RestController
public class TutorialController {


    @Autowired
    private TutorialService tutorialService;


    @DataSource
    @GetMapping("/list")
    public List<Tutorial> list(){
        return tutorialService.list();

    }

    @DataSource(type = DatabaseType.MASTER)
    @GetMapping("/create")
    public Boolean create(){

        Tutorial tutorial = new Tutorial();
        tutorial.setTitle("master");
        tutorial.setDescription("master");

        return tutorialService.save(tutorial);
    }
}

使用POSTMAN發送請求

http://localhost:8082/list

http://localhost:8082/create
#代碼地址
https://github.com/bangbangzhou/spring-boot-dynamic-master-slave.git

責任編輯:武曉燕 來源: springboot葵花寶典
相關推薦

2023-06-07 08:08:37

MybatisSpringBoot

2025-01-17 09:11:51

2020-12-31 07:55:33

spring bootMybatis數據庫

2024-07-31 09:56:20

2025-02-10 10:55:16

2025-05-26 03:20:00

SpringMyBatis數據權限

2025-01-15 15:47:36

2024-07-04 08:00:24

2024-03-01 18:33:59

MySQL節點數據

2021-06-08 07:48:27

MySQL主從配置

2023-01-04 09:33:31

SpringBootMybatis

2024-12-20 16:49:15

MyBatis開發代碼

2023-03-19 11:53:27

2024-11-15 15:27:09

2025-04-07 00:00:00

MySQL數據庫服務器

2023-03-19 22:38:12

邏輯復制PostgreSQL

2022-05-10 10:43:35

數據源動態切換Spring

2023-10-18 15:25:29

數據源數據庫

2024-07-15 09:14:03

MySQL主從復制

2023-07-03 08:57:45

Master服務TCP
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久一区二区精品 | 欧美一区精品 | 亚洲一区有码 | 精品日韩一区二区 | 精品免费国产视频 | 二区国产| 草草网 | 久久久精品 | 毛片一区二区三区 | 中文字幕日韩欧美一区二区三区 | 做a的各种视频 | 黄色国产 | 成人精品一区二区 | 国产精品精品久久久 | 欧美亚洲免费 | 三级黄视频在线观看 | 日韩在线免费视频 | av片在线播放 | 国产做a爱片久久毛片 | 色噜噜亚洲男人的天堂 | 国产一区二区三区在线 | 国产精彩视频在线观看 | 国产精品美女视频 | 国产一区二区在线播放 | 国产精品一区二区福利视频 | 老司机狠狠爱 | 国产精品视频一区二区三区 | chinese中国真实乱对白 | 久久久久久久一区 | 国产精品美女久久久久aⅴ国产馆 | 丁香婷婷成人 | 在线一区二区三区 | 成年人网站免费视频 | 国产成人精品亚洲日本在线观看 | 蜜臀久久99精品久久久久久宅男 | av一级 | 国产精品久久久久久久久久久久久久 | 日韩美av | 成人精品一区二区三区四区 | 国产精品99久久久久久www | 永久av|