• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

spring boot动态切换数据源

武飞扬头像
人生就像一场戏!
帮助2

1、添加maven依赖

  1.  
    <?xml version="1.0" encoding="UTF-8"?>
  2.  
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.  
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.  
    <modelVersion>4.0.0</modelVersion>
  5.  
    <parent>
  6.  
    <groupId>org.springframework.boot</groupId>
  7.  
    <artifactId>spring-boot-starter-parent</artifactId>
  8.  
    <version>2.5.1</version>
  9.  
    <relativePath/> <!-- lookup parent from repository -->
  10.  
    </parent>
  11.  
    <groupId>com.data.source</groupId>
  12.  
    <artifactId>mybatis-datasource</artifactId>
  13.  
    <version>0.0.1-SNAPSHOT</version>
  14.  
    <name>mybatis-datasource</name>
  15.  
    <description>Demo project for Spring Boot</description>
  16.  
     
  17.  
    <properties>
  18.  
    <java.version>1.8</java.version>
  19.  
    </properties>
  20.  
     
  21.  
    <dependencies>
  22.  
    <dependency>
  23.  
    <groupId>org.mybatis.spring.boot</groupId>
  24.  
    <artifactId>mybatis-spring-boot-starter</artifactId>
  25.  
    <version>2.2.0</version>
  26.  
    </dependency>
  27.  
    <dependency>
  28.  
    <groupId>org.springframework.boot</groupId>
  29.  
    <artifactId>spring-boot-starter-web</artifactId>
  30.  
    </dependency>
  31.  
     
  32.  
    <dependency>
  33.  
    <groupId>mysql</groupId>
  34.  
    <artifactId>mysql-connector-java</artifactId>
  35.  
    <version>8.0.13</version>
  36.  
    </dependency>
  37.  
    <dependency>
  38.  
    <groupId>org.projectlombok</groupId>
  39.  
    <artifactId>lombok</artifactId>
  40.  
    <optional>true</optional>
  41.  
    </dependency>
  42.  
     
  43.  
    <!--springBoot的aop-->
  44.  
    <dependency>
  45.  
    <groupId>org.springframework.boot</groupId>
  46.  
    <artifactId>spring-boot-starter-aop</artifactId>
  47.  
    </dependency>
  48.  
     
  49.  
    <dependency>
  50.  
    <groupId>com.alibaba</groupId>
  51.  
    <artifactId>druid-spring-boot-starter</artifactId>
  52.  
    <version>1.1.10</version>
  53.  
    </dependency>
  54.  
     
  55.  
    <dependency>
  56.  
    <groupId>org.springframework.boot</groupId>
  57.  
    <artifactId>spring-boot-starter-test</artifactId>
  58.  
    <scope>test</scope>
  59.  
    </dependency>
  60.  
    <dependency>
  61.  
    <groupId>junit</groupId>
  62.  
    <artifactId>junit</artifactId>
  63.  
    <version>4.12</version>
  64.  
    <scope>test</scope>
  65.  
    </dependency>
  66.  
     
  67.  
    </dependencies>
  68.  
     
  69.  
    <build>
  70.  
    <plugins>
  71.  
    <plugin>
  72.  
    <groupId>org.springframework.boot</groupId>
  73.  
    <artifactId>spring-boot-maven-plugin</artifactId>
  74.  
    <configuration>
  75.  
    <excludes>
  76.  
    <exclude>
  77.  
    <groupId>org.projectlombok</groupId>
  78.  
    <artifactId>lombok</artifactId>
  79.  
    </exclude>
  80.  
    </excludes>
  81.  
    </configuration>
  82.  
    </plugin>
  83.  
    </plugins>
  84.  
    </build>
  85.  
     
  86.  
    </project>
学新通

2、配置文件

application.yml

  1.  
    server:
  2.  
    port: 8082
  3.  
    spring:
  4.  
    datasource:
  5.  
    druid:
  6.  
    master:
  7.  
    driver-class-name: com.mysql.jdbc.Driver
  8.  
    username: root
  9.  
    password: 123456
  10.  
    url: jdbc:mysql://localhost:3306/test?characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
  11.  
    slave:
  12.  
    driver-class-name: com.mysql.jdbc.Driver
  13.  
    username: root
  14.  
    password: 123456
  15.  
    url: jdbc:mysql://localhost:3306/shiro?characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
  16.  
    mybatis:
  17.  
    mapper-locations: classpath*:mapper/*.xml
  18.  
    type-aliases-package: com.data.source.mybatisdatasource.entity
学新通

application.properties

  1.  
    #项目端口
  2.  
    server.port=8082
  3.  
    #项目启动路径
  4.  
    #server.servlet.context-path=/mybatisdatasource
  5.  
     
  6.  
    #Mybatis配置
  7.  
    mybatis.type-aliases-package=com.data.source.mybatisdatasource.entity
  8.  
    mybatis.mapper-locations=classpath*:mapper/*.xml
  9.  
     
  10.  
    #多数据
  11.  
    spring.datasource.druid.master.driver-class-name=com.mysql.jdbc.Driver
  12.  
    spring.datasource.druid.master.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
  13.  
    spring.datasource.druid.master.username=root
  14.  
    spring.datasource.druid.master.password=123456
  15.  
     
  16.  
    spring.datasource.druid.slave.driver-class-name=com.mysql.jdbc.Driver
  17.  
    spring.datasource.druid.slave.url=jdbc:mysql://localhost:3306/shiro?characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
  18.  
    spring.datasource.druid.slave.username=root
  19.  
    spring.datasource.druid.slave.password=123456
  20.  
     
学新通

3、数据源属性实体类

注意事项:prefix = "spring.datasource.druid" 跟application.properties配置的对应

  1.  
    import lombok.Data;
  2.  
    import org.springframework.boot.context.properties.ConfigurationProperties;
  3.  
    import org.springframework.stereotype.Component;
  4.  
     
  5.  
    import java.util.Map;
  6.  
     
  7.  
    /**
  8.  
    * 数据源属性
  9.  
    *
  10.  
    * @author mir liu
  11.  
    */
  12.  
    @ConfigurationProperties(prefix = "spring.datasource.druid")
  13.  
    @Data
  14.  
    @Component
  15.  
    public class DataSourceProperties {
  16.  
    private Map<String, String> master;
  17.  
    private Map<String, String> slave;
  18.  
    }
学新通

4、动态数据源切换

  1.  
     
  2.  
    import lombok.extern.slf4j.Slf4j;
  3.  
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
  4.  
     
  5.  
    import javax.sql.DataSource;
  6.  
    import java.util.Map;
  7.  
     
  8.  
     
  9.  
    /**
  10.  
    * 动态数据源切换
  11.  
    * AbstractRoutingDataSource(每执行一次数据库,动态获取DataSource)
  12.  
    */
  13.  
    @Slf4j
  14.  
    public class DynamicDataSource extends AbstractRoutingDataSource {
  15.  
     
  16.  
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
  17.  
     
  18.  
    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
  19.  
    super.setDefaultTargetDataSource(defaultTargetDataSource);
  20.  
    super.setTargetDataSources(targetDataSources);
  21.  
    super.afterPropertiesSet();
  22.  
    }
  23.  
     
  24.  
     
  25.  
    @Override
  26.  
    protected Object determineCurrentLookupKey() {
  27.  
    Object dataSoruce = getDataSource();
  28.  
    return dataSoruce;
  29.  
    }
  30.  
     
  31.  
    public static void setDataSource(String dataSource) {
  32.  
    contextHolder.set(dataSource);
  33.  
    }
  34.  
     
  35.  
    public static String getDataSource() {
  36.  
    return contextHolder.get();
  37.  
    }
  38.  
     
  39.  
    public static void clearDataSource() {
  40.  
    contextHolder.remove();
  41.  
    }
  42.  
    }
学新通

5、多数据源配置类

  1.  
     
  2.  
    import com.alibaba.druid.pool.DruidDataSource;
  3.  
    import org.springframework.beans.factory.annotation.Autowired;
  4.  
    import org.springframework.context.annotation.Bean;
  5.  
    import org.springframework.context.annotation.Configuration;
  6.  
    import org.springframework.context.annotation.Primary;
  7.  
     
  8.  
    import javax.sql.DataSource;
  9.  
    import java.util.HashMap;
  10.  
    import java.util.Map;
  11.  
     
  12.  
    @Configuration
  13.  
    public class DynamicDataSourceConfig {
  14.  
     
  15.  
    @Autowired
  16.  
    private DataSourceProperties dataSourceProperties;
  17.  
     
  18.  
    @Bean
  19.  
    public DataSource master() {
  20.  
    DruidDataSource druidDataSource = new DruidDataSource();
  21.  
    Map<String, String> master = dataSourceProperties.getMaster();
  22.  
    druidDataSource.setUsername(master.get("username"));
  23.  
    druidDataSource.setPassword(master.get("password"));
  24.  
    druidDataSource.setUrl(master.get("url"));
  25.  
    //其他参数配置 省略
  26.  
    return druidDataSource;
  27.  
    }
  28.  
     
  29.  
    @Bean
  30.  
    public DataSource slave() {
  31.  
    DruidDataSource druidDataSource = new DruidDataSource();
  32.  
    Map<String, String> slave = dataSourceProperties.getSlave();
  33.  
    druidDataSource.setUsername(slave.get("username"));
  34.  
    druidDataSource.setPassword(slave.get("password"));
  35.  
    druidDataSource.setUrl(slave.get("url"));
  36.  
    //其他参数配置 省略
  37.  
    return druidDataSource;
  38.  
    }
  39.  
     
  40.  
    @Bean
  41.  
    @Primary
  42.  
    public DynamicDataSource dataSource(DataSource master, DataSource slave) {
  43.  
    Map<Object, Object> map = new HashMap<>(4);
  44.  
    map.put("master", master);
  45.  
    map.put("slave", slave);
  46.  
    return new DynamicDataSource(master, map);
  47.  
    }
  48.  
    }
学新通

6、自定义@DataSource注解

  1.  
    import java.lang.annotation.*;
  2.  
     
  3.  
    /**
  4.  
    * 动态数据源注解,作用于类、接口或者方法上
  5.  
    *
  6.  
    * @author Mr.Liu
  7.  
    */
  8.  
    @Target({ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
  9.  
    @Retention(RetentionPolicy.RUNTIME)
  10.  
    @Documented
  11.  
    public @interface DataSource {
  12.  
     
  13.  
     
  14.  
    /**
  15.  
    * 默认master数据源
  16.  
    */
  17.  
    String name() default "master";
  18.  
     
  19.  
    }
学新通

7、Aop切面类配置

  1.  
     
  2.  
    import com.data.source.mybatisdatasource.annotation.DataSource;
  3.  
    import com.data.source.mybatisdatasource.config.DynamicDataSource;
  4.  
    import lombok.extern.slf4j.Slf4j;
  5.  
    import org.aspectj.lang.ProceedingJoinPoint;
  6.  
    import org.aspectj.lang.annotation.Around;
  7.  
    import org.aspectj.lang.annotation.Aspect;
  8.  
    import org.aspectj.lang.annotation.Pointcut;
  9.  
    import org.aspectj.lang.reflect.MethodSignature;
  10.  
    import org.springframework.core.annotation.Order;
  11.  
    import org.springframework.stereotype.Component;
  12.  
     
  13.  
    import java.lang.reflect.Method;
  14.  
     
  15.  
    /**
  16.  
    * @Author mir liu
  17.  
    * 动态数据源通知
  18.  
    * @Order(-1) 保证在@Transactional之前执行
  19.  
    */
  20.  
    @Aspect
  21.  
    @Order(-1)
  22.  
    @Component
  23.  
    @Slf4j
  24.  
    public class DynamicDattaSourceAspect {
  25.  
     
  26.  
     
  27.  
    @Pointcut("@annotation(com.data.source.mybatisdatasource.annotation.DataSource)")
  28.  
    public void dataSourcePointCut() {
  29.  
    }
  30.  
     
  31.  
    @Around(value = "dataSourcePointCut()")
  32.  
    public Object around(ProceedingJoinPoint point) throws Throwable {
  33.  
    MethodSignature signature = (MethodSignature) point.getSignature();
  34.  
    Method method = signature.getMethod();
  35.  
     
  36.  
    DataSource dataSource = method.getAnnotation(DataSource.class);
  37.  
    log.info("数据库 dataSource:{}", dataSource.toString());
  38.  
    if (dataSource == null) {
  39.  
    DynamicDataSource.setDataSource("master");
  40.  
    } else {
  41.  
    DynamicDataSource.setDataSource(dataSource.name());
  42.  
    }
  43.  
    try {
  44.  
    return point.proceed();
  45.  
    } finally {
  46.  
    DynamicDataSource.clearDataSource();
  47.  
    }
  48.  
    }
  49.  
    }
学新通

8、启动配置注解信息,重要(不然运行会报错)

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})

9、测试

(1)、service层

  1.  
    import com.data.source.mybatisdatasource.annotation.DataSource;
  2.  
    import com.data.source.mybatisdatasource.entity.UserInfo;
  3.  
    import com.data.source.mybatisdatasource.mapper.UserInfoMapper;
  4.  
    import com.data.source.mybatisdatasource.service.DynamicServcice;
  5.  
    import org.springframework.beans.factory.annotation.Autowired;
  6.  
    import org.springframework.stereotype.Service;
  7.  
     
  8.  
    import java.util.List;
  9.  
     
  10.  
     
  11.  
    @Service
  12.  
    public class DynamicServciceImpl implements DynamicServcice {
  13.  
     
  14.  
     
  15.  
    @Autowired
  16.  
    private UserInfoMapper userInfoMapper;
  17.  
     
  18.  
     
  19.  
    @DataSource(name = "slave")
  20.  
    @Override
  21.  
    public List<UserInfo> selectAll() {
  22.  
    return userInfoMapper.selectAll();
  23.  
    }
  24.  
     
  25.  
     
  26.  
    @DataSource(name = "master")
  27.  
    @Override
  28.  
    public int insert(UserInfo record) {
  29.  
    return userInfoMapper.insert(record);
  30.  
    }
  31.  
    }
学新通

(2)、单元测试

  1.  
     
  2.  
    import com.data.source.mybatisdatasource.entity.UserInfo;
  3.  
    import com.data.source.mybatisdatasource.service.DynamicServcice;
  4.  
    import org.junit.jupiter.api.Test;
  5.  
    import org.junit.runner.RunWith;
  6.  
    import org.springframework.beans.factory.annotation.Autowired;
  7.  
    import org.springframework.boot.test.context.SpringBootTest;
  8.  
    import org.springframework.test.context.junit4.SpringRunner;
  9.  
     
  10.  
    import java.util.Date;
  11.  
    import java.util.List;
  12.  
     
  13.  
    @SpringBootTest
  14.  
    @RunWith(SpringRunner.class)
  15.  
    class MybatisDatasourceApplicationTests {
  16.  
     
  17.  
    @Autowired
  18.  
    private DynamicServcice dynamicServcice;
  19.  
     
  20.  
     
  21.  
    @Test
  22.  
    void master() {
  23.  
    UserInfo userInfo = new UserInfo();
  24.  
    userInfo.setUserId("acoi112");
  25.  
    userInfo.setUserName("小龙女");
  26.  
    userInfo.setCreatTime(new Date());
  27.  
    userInfo.setModifyDate(new Date());
  28.  
    Integer num = dynamicServcice.insertSelective(userInfo);
  29.  
    }
  30.  
     
  31.  
    @Test
  32.  
    void slave() {
  33.  
    List<UserInfo> userInfoList = dynamicServcice.selectAll();
  34.  
    System.out.println();
  35.  
    }
  36.  
     
  37.  
    @Test
  38.  
    void masterAndSlave() {
  39.  
    List<UserInfo> userInfoList = dynamicServcice.selectAll();
  40.  
    System.out.println();
  41.  
    }
  42.  
    }
学新通

测试结果

  1.  
    2022-01-06 15:23:22.424 [main] INFO c.d.s.m.aop.DynamicDattaSourceAspect - 数据库 dataSource:@com.data.source.mybatisdatasource.annotation.DataSource(name=master)
  2.  
    2022-01-06 15:23:22.450 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
  3.  
     
  4.  
    2022-01-06 15:29:48.581 [main] INFO c.d.s.m.aop.DynamicDattaSourceAspect - 数据库 dataSource:@com.data.source.mybatisdatasource.annotation.DataSource(name=slave)
  5.  
    2022-01-06 15:29:48.610 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhiaiiea
系列文章
更多 icon
同类精品
更多 icon
继续加载