Spring Boot + MyBatis-Plus 读写分离与多 Slave 负载均衡示例

发布于:2025-06-04 ⋅ 阅读:(26) ⋅ 点赞:(0)

Spring Boot + MyBatis-Plus 读写分离与多 Slave 负载均衡示例

一、项目结构

src/main/java/com/example/demo/
├── config/
│   ├── DataSourceConfig.java         # 数据源配置
│   ├── MyBatisPlusConfig.java        # MyBatis-Plus配置
├── constant/
│   ├── DataSourceType.java           # 数据源类型枚举
├── context/
│   ├── DataSourceContextHolder.java  # 数据源上下文
├── aspect/
│   ├── DataSourceAspect.java         # 注解驱动的数据源切换
│   ├── DataSourceRouteAspect.java    # 自动路由的数据源切换
├── annotation/
│   ├── DataSource.java               # 自定义数据源注解
├── loadbalancer/
│   ├── SlaveDataSourceLoadBalancer.java # 从库负载均衡器
├── mapper/
│   ├── UserMapper.java               # DAO接口
├── service/
│   ├── UserService.java              # 服务接口
│   ├── impl/
│       └── UserServiceImpl.java      # 服务实现
├── controller/
│   ├── UserController.java           # 控制器
└── DemoApplication.java              # 启动类

二、核心代码实现

(一)数据源类型枚举

// constant/DataSourceType.java
package com.example.demo.constant;

public enum DataSourceType {
   
    MASTER,
    SLAVE_1,
    SLAVE_2,
    SLAVE_3
}

(二)数据源上下文

// context/DataSourceContextHolder.java
package com.example.demo.context;

import com.example.demo.constant.DataSourceType;

public class DataSourceContextHolder {
   
    private static final ThreadLocal<DataSourceType> contextHolder = new ThreadLocal<>();

    public static void setDataSource(DataSourceType type) {
   
        contextHolder.set(type);
    }

    public static DataSourceType getDataSource() {
   
        return contextHolder.get();
    }

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

(三)动态数据源

// config/DynamicRoutingDataSource.java
package com.example.demo.config;

import com.example.demo.context.DataSourceContextHolder;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
   
    @Override
    protected Object determineCurrentLookupKey() {
   
        return DataSourceContextHolder.getDataSource();
    }
}

(四)数据源配置

// config/DataSourceConfig.java
package com.example.demo.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.example.demo.constant.DataSourceType;
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 javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class DataSourceConfig {
   

    @Primary
    @Bean(name = "masterDataSource")
    @ConfigurationProperties("spring.datasource.master")
    public DataSource masterDataSource() {
   
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "slave1DataSource")
    @ConfigurationProperties("spring.datasource.slave1")
    public DataSource slave1DataSource() {
   
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "slave2DataSource")
    @ConfigurationProperties("spring.datasource.slave2")
    public DataSource slave2DataSource() {
   
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "slave3DataSource")
    @ConfigurationProperties("spring.datasource.slave3")
    public DataSource slave3DataSource() {
   
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    public DataSource dynamicDataSource() {
   
        DynamicRoutingDataSource dynamicDataSource = new DynamicRoutingDataSource();
        
        // 设置默认数据源
        dynamicDataSource.setDefaultTargetDataSource(masterDataSource());
        
        // 设置多数据源映射
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MASTER, masterDataSource());
        targetDataSources.put(

网站公告

今日签到

点亮在社区的每一天
去签到