欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring Boot + Mybatis 實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源案例分析

 更新時(shí)間:2018年11月02日 08:32:37   作者:朝雨憶輕塵  
這篇文章主要介紹了Spring Boot + Mybatis 實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源,需要的朋友可以參考下

動(dòng)態(tài)數(shù)據(jù)源

在很多具體應(yīng)用場(chǎng)景的時(shí)候,我們需要用到動(dòng)態(tài)數(shù)據(jù)源的情況,比如多租戶的場(chǎng)景,系統(tǒng)登錄時(shí)需要根據(jù)用戶信息切換到用戶對(duì)應(yīng)的數(shù)據(jù)庫(kù)。又比如業(yè)務(wù)A要訪問(wèn)A數(shù)據(jù)庫(kù),業(yè)務(wù)B要訪問(wèn)B數(shù)據(jù)庫(kù)等,都可以使用動(dòng)態(tài)數(shù)據(jù)源方案進(jìn)行解決。接下來(lái),我們就來(lái)講解如何實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源,以及在過(guò)程中剖析動(dòng)態(tài)數(shù)據(jù)源背后的實(shí)現(xiàn)原理。

實(shí)現(xiàn)案例

本教程案例基于 Spring Boot + Mybatis + MySQL 實(shí)現(xiàn)。

數(shù)據(jù)庫(kù)設(shè)計(jì)

首先需要安裝好MySQL數(shù)據(jù)庫(kù),新建數(shù)據(jù)庫(kù) master,slave,分別創(chuàng)建用戶表,用來(lái)測(cè)試數(shù)據(jù)源,SQL腳本如下。

-- ----------------------------------------------------
-- 用戶
-- ----------------------------------------------------
-- Table structure for `sys_user`
-- ----------------------------------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
 `id` bigint NOT NULL AUTO_INCREMENT COMMENT '編號(hào)',
 `name` varchar(50) NOT NULL COMMENT '用戶名',
 `password` varchar(100) COMMENT '密碼',
 `salt` varchar(40) COMMENT '鹽',
 `email` varchar(100) COMMENT '郵箱',
 `mobile` varchar(100) COMMENT '手機(jī)號(hào)',
 `status` tinyint COMMENT '狀態(tài) 0:禁用 1:正常',
 `dept_id` bigint(20) COMMENT '機(jī)構(gòu)ID',
 `create_by` varchar(50) COMMENT '創(chuàng)建人',
 `create_time` datetime COMMENT '創(chuàng)建時(shí)間',
 `last_update_by` varchar(50) COMMENT '更新人',
 `last_update_time` datetime COMMENT '更新時(shí)間',
 `del_flag` tinyint DEFAULT 0 COMMENT '是否刪除 -1:已刪除 0:正常',
 PRIMARY KEY (`id`),
 UNIQUE INDEX (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶';

新建工程

新建一個(gè)Spring Boot工程,最終代碼結(jié)構(gòu)如下。

添加依賴

添加Spring Boot,Spring Aop,Mybatis,MySQL,Swagger相關(guān)依賴。Swagger方便用來(lái)測(cè)試接口。

pom.xml

<?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>top.ivan.demo</groupId>
 <artifactId>springboot-dynamic-datasource</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>springboot-dynamic-datasource</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>
  <mybatis.spring.version>1.3.2</mybatis.spring.version>
  <swagger.version>2.8.0</swagger.version>
 </properties>

 <dependencies>
   <!-- spring boot -->
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
  <!-- spring aop -->
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-aop</artifactId>
  </dependency>
  <!-- mybatis -->
  <dependency>
   <groupId>org.mybatis.spring.boot</groupId>
   <artifactId>mybatis-spring-boot-starter</artifactId>
   <version>${mybatis.spring.version}</version>
  </dependency>
  <!-- mysql -->
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
  </dependency>
  <!-- swagger -->
  <dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>${swagger.version}</version>
  </dependency>
  <dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>${swagger.version}</version>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>

</project>

配置文件

修改配置文件,添加兩個(gè)數(shù)據(jù)源,可以是同一個(gè)主機(jī)地址的兩個(gè)數(shù)據(jù)庫(kù)master,slave,也可是兩個(gè)不同主機(jī)的地址,根據(jù)實(shí)際情況配置。

application.yml

spring:
 datasource:
 master:
  driver-class-name: com.mysql.jdbc.Driver
  type: com.zaxxer.hikari.HikariDataSource
  jdbcUrl: jdbc:mysql://127.0.0.1:3306/master?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8
  username: root
  password: 123
 slave:
  driver-class-name: com.mysql.jdbc.Driver
  type: com.zaxxer.hikari.HikariDataSource
  jdbcUrl: jdbc:mysql://127.0.0.1:3306/slave?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8
  username: root
  password: 123

啟動(dòng)類

啟動(dòng)類添加 exclude = {DataSourceAutoConfiguration.class}, 以禁用數(shù)據(jù)源默認(rèn)自動(dòng)配置。

數(shù)據(jù)源默認(rèn)自動(dòng)配置會(huì)讀取 spring.datasource.* 的屬性創(chuàng)建數(shù)據(jù)源,所以要禁用以進(jìn)行定制。

@ComponentScan(basePackages = "com.louis.springboot") 是掃描范圍,都知道不用多說(shuō)。

DynamicDatasourceApplication.java

package com.louis.springboot.dynamic.datasource;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

/**
 * 啟動(dòng)器
 * @author Louis
 * @date Oct 31, 2018
 */
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) // 禁用數(shù)據(jù)源自動(dòng)配置
@ComponentScan(basePackages = "com.louis.springboot")
public class DynamicDatasourceApplication {

 public static void main(String[] args) {
  SpringApplication.run(DynamicDatasourceApplication.class, args);
 }
}

數(shù)據(jù)源配置類

創(chuàng)建一個(gè)數(shù)據(jù)源配置類,主要做以下幾件事情:

1. 配置 dao,model,xml mapper文件的掃描路徑。

2. 注入數(shù)據(jù)源配置屬性,創(chuàng)建master、slave數(shù)據(jù)源。

3. 創(chuàng)建一個(gè)動(dòng)態(tài)數(shù)據(jù)源,并裝入master、slave數(shù)據(jù)源。

4. 將動(dòng)態(tài)數(shù)據(jù)源設(shè)置到SQL會(huì)話工廠和事務(wù)管理器。

如此,當(dāng)進(jìn)行數(shù)據(jù)庫(kù)操作時(shí),就會(huì)通過(guò)我們創(chuàng)建的動(dòng)態(tài)數(shù)據(jù)源去獲取要操作的數(shù)據(jù)源了。

package com.louis.springboot.dynamic.datasource.config;

import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
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 org.springframework.transaction.PlatformTransactionManager;

import com.louis.springboot.dynamic.datasource.dds.DynamicDataSource;

/**
 * Mybatis配置
 * @author Louis
 * @date Oct 31, 2018
 */
@Configuration
@MapperScan(basePackages = {"com.louis.**.dao"}) // 掃描DAO
public class MybatisConfig {

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

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

 @Bean("dynamicDataSource")
 public DataSource dynamicDataSource() {
  DynamicDataSource dynamicDataSource = new DynamicDataSource();
  Map<Object, Object> dataSourceMap = new HashMap<>(2);
  dataSourceMap.put("master", master());
  dataSourceMap.put("slave", slave());
  // 將 master 數(shù)據(jù)源作為默認(rèn)指定的數(shù)據(jù)源
  dynamicDataSource.setDefaultDataSource(master());
  // 將 master 和 slave 數(shù)據(jù)源作為指定的數(shù)據(jù)源
  dynamicDataSource.setDataSources(dataSourceMap);
  return dynamicDataSource;
 }

 @Bean
 public SqlSessionFactoryBean sqlSessionFactoryBean() throws Exception {
  SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
  // 配置數(shù)據(jù)源,此處配置為關(guān)鍵配置,如果沒(méi)有將 dynamicDataSource作為數(shù)據(jù)源則不能實(shí)現(xiàn)切換
  sessionFactory.setDataSource(dynamicDataSource());
  sessionFactory.setTypeAliasesPackage("com.louis.**.model"); // 掃描Model
  PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
  sessionFactory.setMapperLocations(resolver.getResources("classpath*:**/sqlmap/*.xml")); // 掃描映射文件
  return sessionFactory;
 }

 @Bean
 public PlatformTransactionManager transactionManager() {
  // 配置事務(wù)管理, 使用事務(wù)時(shí)在方法頭部添加@Transactional注解即可
  return new DataSourceTransactionManager(dynamicDataSource());
 }
}

動(dòng)態(tài)數(shù)據(jù)源類

我們上一步把這個(gè)動(dòng)態(tài)數(shù)據(jù)源設(shè)置到了SQL會(huì)話工廠和事務(wù)管理器,這樣在操作數(shù)據(jù)庫(kù)時(shí)就會(huì)通過(guò)動(dòng)態(tài)數(shù)據(jù)源類來(lái)獲取要操作的數(shù)據(jù)源了。

動(dòng)態(tài)數(shù)據(jù)源類集成了Spring提供的AbstractRoutingDataSource類,AbstractRoutingDataSource 中 獲取數(shù)據(jù)源的方法就是 determineTargetDataSource,而此方法又通過(guò) determineCurrentLookupKey 方法獲取查詢數(shù)據(jù)源的key。

所以如果我們需要?jiǎng)討B(tài)切換數(shù)據(jù)源,就可以通過(guò)以下兩種方式定制:

1. 覆寫 determineCurrentLookupKey 方法

通過(guò)覆寫 determineCurrentLookupKey 方法,從一個(gè)自定義的 DynamicDataSourceContextHolder.getDataSourceKey() 獲取數(shù)據(jù)源key值,這樣在我們想動(dòng)態(tài)切換數(shù)據(jù)源的時(shí)候,只要通過(guò)  DynamicDataSourceContextHolder.setDataSourceKey(key)  的方式就可以動(dòng)態(tài)改變數(shù)據(jù)源了。這種方式要求在獲取數(shù)據(jù)源之前,要先初始化各個(gè)數(shù)據(jù)源到 DynamicDataSource 中,我們案例就是采用這種方式實(shí)現(xiàn)的,所以在 MybatisConfig 中把master和slave數(shù)據(jù)源都事先初始化到DynamicDataSource 中。

2. 可以通過(guò)覆寫 determineTargetDataSource,因?yàn)閿?shù)據(jù)源就是在這個(gè)方法創(chuàng)建并返回的,所以這種方式就比較自由了,支持到任何你希望的地方讀取數(shù)據(jù)源信息,只要最終返回一個(gè) DataSource 的實(shí)現(xiàn)類即可。比如你可以到數(shù)據(jù)庫(kù)、本地文件、網(wǎng)絡(luò)接口等方式讀取到數(shù)據(jù)源信息然后返回相應(yīng)的數(shù)據(jù)源對(duì)象就可以了。

DynamicDataSource.java

package com.louis.springboot.dynamic.datasource.dds;

import java.util.Map;

import javax.sql.DataSource;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * 動(dòng)態(tài)數(shù)據(jù)源實(shí)現(xiàn)類
 * @author Louis
 * @date Oct 31, 2018
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
  
  
  /**
   * 如果不希望數(shù)據(jù)源在啟動(dòng)配置時(shí)就加載好,可以定制這個(gè)方法,從任何你希望的地方讀取并返回?cái)?shù)據(jù)源
   * 比如從數(shù)據(jù)庫(kù)、文件、外部接口等讀取數(shù)據(jù)源信息,并最終返回一個(gè)DataSource實(shí)現(xiàn)類對(duì)象即可
   */
  @Override
  protected DataSource determineTargetDataSource() {
    return super.determineTargetDataSource();
  }
  
  /**
   * 如果希望所有數(shù)據(jù)源在啟動(dòng)配置時(shí)就加載好,這里通過(guò)設(shè)置數(shù)據(jù)源Key值來(lái)切換數(shù)據(jù),定制這個(gè)方法
   */
  @Override
  protected Object determineCurrentLookupKey() {
    return DynamicDataSourceContextHolder.getDataSourceKey();
  }
  
  /**
   * 設(shè)置默認(rèn)數(shù)據(jù)源
   * @param defaultDataSource
   */
  public void setDefaultDataSource(Object defaultDataSource) {
    super.setDefaultTargetDataSource(defaultDataSource);
  }
  
  /**
   * 設(shè)置數(shù)據(jù)源
   * @param dataSources
   */
  public void setDataSources(Map<Object, Object> dataSources) {
    super.setTargetDataSources(dataSources);
    // 將數(shù)據(jù)源的 key 放到數(shù)據(jù)源上下文的 key 集合中,用于切換時(shí)判斷數(shù)據(jù)源是否有效
    DynamicDataSourceContextHolder.addDataSourceKeys(dataSources.keySet());
  }
}

數(shù)據(jù)源上下文

動(dòng)態(tài)數(shù)據(jù)源的切換主要是通過(guò)調(diào)用這個(gè)類的方法來(lái)完成的。在任何想要進(jìn)行切換數(shù)據(jù)源的時(shí)候都可以通過(guò)調(diào)用這個(gè)類的方法實(shí)現(xiàn)切換。比如系統(tǒng)登錄時(shí),根據(jù)用戶信息調(diào)用這個(gè)類的數(shù)據(jù)源切換方法切換到用戶對(duì)應(yīng)的數(shù)據(jù)庫(kù)。

主要方法介紹:

1. 切換數(shù)據(jù)源

在任何想要進(jìn)行切換數(shù)據(jù)源的時(shí)候都可以通過(guò)調(diào)用這個(gè)類的方法實(shí)現(xiàn)切換。

  /**
   * 切換數(shù)據(jù)源
   * @param key
   */
  public static void setDataSourceKey(String key) {
    contextHolder.set(key);
  }

2. 重置數(shù)據(jù)源

將數(shù)據(jù)源重置回默認(rèn)的數(shù)據(jù)源。默認(rèn)數(shù)據(jù)源通過(guò) DynamicDataSource.setDefaultDataSource(ds) 進(jìn)行設(shè)置。

  /**
   * 重置數(shù)據(jù)源
   */
  public static void clearDataSourceKey() {
    contextHolder.remove();
  }

3. 獲取當(dāng)前數(shù)據(jù)源key

  /**
   * 獲取數(shù)據(jù)源
   * @return
   */
  public static String getDataSourceKey() {
    return contextHolder.get();
  }

完整代碼如下

DynamicDataSourceContextHolder.java

package com.louis.springboot.dynamic.datasource.dds;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 動(dòng)態(tài)數(shù)據(jù)源上下文
 * @author Louis
 * @date Oct 31, 2018
 */
public class DynamicDataSourceContextHolder {

  private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>() {
    /**
     * 將 master 數(shù)據(jù)源的 key作為默認(rèn)數(shù)據(jù)源的 key
     */
    @Override
    protected String initialValue() {
      return "master";
    }
  };


  /**
   * 數(shù)據(jù)源的 key集合,用于切換時(shí)判斷數(shù)據(jù)源是否存在
   */
  public static List<Object> dataSourceKeys = new ArrayList<>();

  /**
   * 切換數(shù)據(jù)源
   * @param key
   */
  public static void setDataSourceKey(String key) {
    contextHolder.set(key);
  }

  /**
   * 獲取數(shù)據(jù)源
   * @return
   */
  public static String getDataSourceKey() {
    return contextHolder.get();
  }

  /**
   * 重置數(shù)據(jù)源
   */
  public static void clearDataSourceKey() {
    contextHolder.remove();
  }

  /**
   * 判斷是否包含數(shù)據(jù)源
   * @param key 數(shù)據(jù)源key
   * @return
   */
  public static boolean containDataSourceKey(String key) {
    return dataSourceKeys.contains(key);
  }
  
  /**
   * 添加數(shù)據(jù)源keys
   * @param keys
   * @return
   */
  public static boolean addDataSourceKeys(Collection<? extends Object> keys) {
    return dataSourceKeys.addAll(keys);
  }
}

注解式數(shù)據(jù)源

到這里,在任何想要?jiǎng)討B(tài)切換數(shù)據(jù)源的時(shí)候,只要調(diào)用  DynamicDataSourceContextHolder.setDataSourceKey(key)  就可以完成了。

接下來(lái)我們實(shí)現(xiàn)通過(guò)注解的方式來(lái)進(jìn)行數(shù)據(jù)源的切換,原理就是添加注解(如@DataSource(value="master")),然后實(shí)現(xiàn)注解切面進(jìn)行數(shù)據(jù)源切換。

創(chuàng)建一個(gè)動(dòng)態(tài)數(shù)據(jù)源注解,擁有一個(gè)value值,用于標(biāo)識(shí)要切換的數(shù)據(jù)源的key。

DataSource.java

package com.louis.springboot.dynamic.datasource.dds;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 動(dòng)態(tài)數(shù)據(jù)源注解
 * @author Louis
 * @date Oct 31, 2018
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
  
  /**
   * 數(shù)據(jù)源key值
   * @return
   */
  String value();
  
}

創(chuàng)建一個(gè)AOP切面,攔截帶 @DataSource 注解的方法,在方法執(zhí)行前切換至目標(biāo)數(shù)據(jù)源,執(zhí)行完成后恢復(fù)到默認(rèn)數(shù)據(jù)源。

DynamicDataSourceAspect.java

package com.louis.springboot.dynamic.datasource.dds;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 動(dòng)態(tài)數(shù)據(jù)源切換處理器
 * @author Louis
 * @date Oct 31, 2018
 */
@Aspect
@Order(-1) // 該切面應(yīng)當(dāng)先于 @Transactional 執(zhí)行
@Component
public class DynamicDataSourceAspect {
  
  /**
   * 切換數(shù)據(jù)源
   * @param point
   * @param dataSource
   */
  @Before("@annotation(dataSource))")
  public void switchDataSource(JoinPoint point, DataSource dataSource) {
    if (!DynamicDataSourceContextHolder.containDataSourceKey(dataSource.value())) {
      System.out.println("DataSource [{}] doesn't exist, use default DataSource [{}] " + dataSource.value());
    } else {
      // 切換數(shù)據(jù)源
      DynamicDataSourceContextHolder.setDataSourceKey(dataSource.value());
      System.out.println("Switch DataSource to [" + DynamicDataSourceContextHolder.getDataSourceKey()
        + "] in Method [" + point.getSignature() + "]");
    }
  }

  /**
   * 重置數(shù)據(jù)源
   * @param point
   * @param dataSource
   */
  @After("@annotation(dataSource))")
  public void restoreDataSource(JoinPoint point, DataSource dataSource) {
    // 將數(shù)據(jù)源置為默認(rèn)數(shù)據(jù)源
    DynamicDataSourceContextHolder.clearDataSourceKey();
    System.out.println("Restore DataSource to [" + DynamicDataSourceContextHolder.getDataSourceKey() 
      + "] in Method [" + point.getSignature() + "]");
  }
}

到這里,動(dòng)態(tài)數(shù)據(jù)源相關(guān)的處理代碼就完成了。

編寫用戶業(yè)務(wù)代碼

接下來(lái)編寫用戶查詢業(yè)務(wù)代碼,用來(lái)進(jìn)行測(cè)試,只需添加一個(gè)查詢接口即可。

編寫一個(gè)控制器,包含兩個(gè)查詢方法,分別注解 master 和 slave 數(shù)據(jù)源。

SysUserController.java
package com.louis.springboot.dynamic.datasource.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.louis.springboot.dynamic.datasource.dds.DataSource;
import com.louis.springboot.dynamic.datasource.service.SysUserService;
/**
 * 用戶控制器
 * @author Louis
 * @date Oct 31, 2018
 */
@RestController
@RequestMapping("user")
public class SysUserController {
  @Autowired
  private SysUserService sysUserService;
  @DataSource(value="master")
  @PostMapping(value="/findAll")
  public Object findAll() {
    return sysUserService.findAll();
  }
  @DataSource(value="slave")
  @PostMapping(value="/findAll2")
  public Object findAll2() {
    return sysUserService.findAll();
  }
}

下面是正常的業(yè)務(wù)代碼,沒(méi)有什么好說(shuō)明的,直接貼代碼了。

SysUser.java
public class SysUser {
  private Long id;
  private String name;
  private String password;
  private String salt;
  private String email;
  private String mobile;
  private Byte status;
  private Long deptId;
  private String deptName;
  private Byte delFlag;
  private String createBy;
  private Date createTime;
  private String lastUpdateBy;
  private Date lastUpdateTime;
  ...setter and getter
}
SysUserMapper.java
package com.louis.springboot.dynamic.datasource.dao;
import java.util.List;
import com.louis.springboot.dynamic.datasource.model.SysUser;
public interface SysUserMapper {
  int deleteByPrimaryKey(Long id);
  int insert(SysUser record);
  int insertSelective(SysUser record);
  SysUser selectByPrimaryKey(Long id);
  int updateByPrimaryKeySelective(SysUser record);
  int updateByPrimaryKey(SysUser record);
  List<SysUser> findAll();
}

SysUserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.louis.springboot.dynamic.datasource.dao.SysUserMapper">
 <resultMap id="BaseResultMap" type="com.louis.springboot.dynamic.datasource.model.SysUser">
  <id column="id" jdbcType="BIGINT" property="id" />
  <result column="name" jdbcType="VARCHAR" property="name" />
  <result column="password" jdbcType="VARCHAR" property="password" />
  <result column="salt" jdbcType="VARCHAR" property="salt" />
  <result column="email" jdbcType="VARCHAR" property="email" />
  <result column="mobile" jdbcType="VARCHAR" property="mobile" />
  <result column="status" jdbcType="TINYINT" property="status" />
  <result column="dept_id" jdbcType="BIGINT" property="deptId" />
  <result column="create_by" jdbcType="BIGINT" property="createBy" />
  <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
  <result column="last_update_by" jdbcType="BIGINT" property="lastUpdateBy" />
  <result column="last_update_time" jdbcType="TIMESTAMP" property="lastUpdateTime" />
  <result column="del_flag" jdbcType="TINYINT" property="delFlag" />
 </resultMap>
 <sql id="Base_Column_List">
  id, name, password, salt, email, mobile, status, dept_id, create_by, create_time, 
  last_update_by, last_update_time, del_flag
 </sql>
 <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
  select 
  <include refid="Base_Column_List" />
  from sys_user
  where id = #{id,jdbcType=BIGINT}
 </select>
 <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
  delete from sys_user
  where id = #{id,jdbcType=BIGINT}
 </delete>
 <insert id="insert" parameterType="com.louis.springboot.dynamic.datasource.model.SysUser">
  insert into sys_user (id, name, password, 
   salt, email, mobile, 
   status, dept_id, create_by, 
   create_time, last_update_by, last_update_time, 
   del_flag)
  values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, 
   #{salt,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{mobile,jdbcType=VARCHAR}, 
   #{status,jdbcType=TINYINT}, #{deptId,jdbcType=BIGINT}, #{createBy,jdbcType=BIGINT}, 
   #{createTime,jdbcType=TIMESTAMP}, #{lastUpdateBy,jdbcType=BIGINT}, #{lastUpdateTime,jdbcType=TIMESTAMP}, 
   #{delFlag,jdbcType=TINYINT})
 </insert>
 <insert id="insertSelective" parameterType="com.louis.springboot.dynamic.datasource.model.SysUser">
  insert into sys_user
  <trim prefix="(" suffix=")" suffixOverrides=",">
   <if test="id != null">
    id,
   </if>
   <if test="name != null">
    name,
   </if>
   <if test="password != null">
    password,
   </if>
   <if test="salt != null">
    salt,
   </if>
   <if test="email != null">
    email,
   </if>
   <if test="mobile != null">
    mobile,
   </if>
   <if test="status != null">
    status,
   </if>
   <if test="deptId != null">
    dept_id,
   </if>
   <if test="createBy != null">
    create_by,
   </if>
   <if test="createTime != null">
    create_time,
   </if>
   <if test="lastUpdateBy != null">
    last_update_by,
   </if>
   <if test="lastUpdateTime != null">
    last_update_time,
   </if>
   <if test="delFlag != null">
    del_flag,
   </if>
  </trim>
  <trim prefix="values (" suffix=")" suffixOverrides=",">
   <if test="id != null">
    #{id,jdbcType=BIGINT},
   </if>
   <if test="name != null">
    #{name,jdbcType=VARCHAR},
   </if>
   <if test="password != null">
    #{password,jdbcType=VARCHAR},
   </if>
   <if test="salt != null">
    #{salt,jdbcType=VARCHAR},
   </if>
   <if test="email != null">
    #{email,jdbcType=VARCHAR},
   </if>
   <if test="mobile != null">
    #{mobile,jdbcType=VARCHAR},
   </if>
   <if test="status != null">
    #{status,jdbcType=TINYINT},
   </if>
   <if test="deptId != null">
    #{deptId,jdbcType=BIGINT},
   </if>
   <if test="createBy != null">
    #{createBy,jdbcType=BIGINT},
   </if>
   <if test="createTime != null">
    #{createTime,jdbcType=TIMESTAMP},
   </if>
   <if test="lastUpdateBy != null">
    #{lastUpdateBy,jdbcType=BIGINT},
   </if>
   <if test="lastUpdateTime != null">
    #{lastUpdateTime,jdbcType=TIMESTAMP},
   </if>
   <if test="delFlag != null">
    #{delFlag,jdbcType=TINYINT},
   </if>
  </trim>
 </insert>
 <update id="updateByPrimaryKeySelective" parameterType="com.louis.springboot.dynamic.datasource.model.SysUser">
  update sys_user
  <set>
   <if test="name != null">
    name = #{name,jdbcType=VARCHAR},
   </if>
   <if test="password != null">
    password = #{password,jdbcType=VARCHAR},
   </if>
   <if test="salt != null">
    salt = #{salt,jdbcType=VARCHAR},
   </if>
   <if test="email != null">
    email = #{email,jdbcType=VARCHAR},
   </if>
   <if test="mobile != null">
    mobile = #{mobile,jdbcType=VARCHAR},
   </if>
   <if test="status != null">
    status = #{status,jdbcType=TINYINT},
   </if>
   <if test="deptId != null">
    dept_id = #{deptId,jdbcType=BIGINT},
   </if>
   <if test="createBy != null">
    create_by = #{createBy,jdbcType=BIGINT},
   </if>
   <if test="createTime != null">
    create_time = #{createTime,jdbcType=TIMESTAMP},
   </if>
   <if test="lastUpdateBy != null">
    last_update_by = #{lastUpdateBy,jdbcType=BIGINT},
   </if>
   <if test="lastUpdateTime != null">
    last_update_time = #{lastUpdateTime,jdbcType=TIMESTAMP},
   </if>
   <if test="delFlag != null">
    del_flag = #{delFlag,jdbcType=TINYINT},
   </if>
  </set>
  where id = #{id,jdbcType=BIGINT}
 </update>
 <update id="updateByPrimaryKey" parameterType="com.louis.springboot.dynamic.datasource.model.SysUser">
  update sys_user
  set name = #{name,jdbcType=VARCHAR},
   password = #{password,jdbcType=VARCHAR},
   salt = #{salt,jdbcType=VARCHAR},
   email = #{email,jdbcType=VARCHAR},
   mobile = #{mobile,jdbcType=VARCHAR},
   status = #{status,jdbcType=TINYINT},
   dept_id = #{deptId,jdbcType=BIGINT},
   create_by = #{createBy,jdbcType=BIGINT},
   create_time = #{createTime,jdbcType=TIMESTAMP},
   last_update_by = #{lastUpdateBy,jdbcType=BIGINT},
   last_update_time = #{lastUpdateTime,jdbcType=TIMESTAMP},
   del_flag = #{delFlag,jdbcType=TINYINT}
  where id = #{id,jdbcType=BIGINT}
 </update>
 <select id="findAll" resultMap="BaseResultMap">
  select 
  <include refid="Base_Column_List" />
  from sys_user
 </select>
</mapper>

SysUserService.java

package com.louis.springboot.dynamic.datasource.service;
import java.util.List;
import com.louis.springboot.dynamic.datasource.model.SysUser;
/**
 * 用戶管理
 * @author Louis
 * @date Oct 31, 2018
 */
public interface SysUserService {
  /**
   * 查找全部用戶信息
   * @return
   */
  List<SysUser> findAll();
}
SysUserServiceImpl.java
package com.louis.springboot.dynamic.datasource.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.louis.springboot.dynamic.datasource.dao.SysUserMapper;
import com.louis.springboot.dynamic.datasource.model.SysUser;
import com.louis.springboot.dynamic.datasource.service.SysUserService;
@Service
public class SysUserServiceImpl implements SysUserService {
  @Autowired
  private SysUserMapper sysUserMapper;
  /**
   * 查找全部用戶信息
   * @return
   */
  public List<SysUser> findAll() {
    return sysUserMapper.findAll();
  }
}

測(cè)試效果

啟動(dòng)系統(tǒng),訪問(wèn)  http://localhost:8080/swagger-ui.html ,分別測(cè)試兩個(gè)接口,成功返回?cái)?shù)據(jù)。

user/findAll (master數(shù)據(jù)源)

 

user/findAll2 (slave數(shù)據(jù)源)

源碼下載

碼云:https://gitee.com/liuge1988/spring-boot-demo.git

總結(jié)

以上所述是小編給大家介紹的Spring Boot + Mybatis 實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源案例分析,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Java8 Comparator排序方法實(shí)例詳解

    Java8 Comparator排序方法實(shí)例詳解

    這篇文章主要介紹了Java8 Comparator排序方法實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • java文件輸出流寫文件的幾種方法

    java文件輸出流寫文件的幾種方法

    這篇文章主要介紹了java文件輸出流寫文件的幾種方法,需要的朋友可以參考下
    2014-04-04
  • java按字節(jié)截取帶有漢字的字符串的解法(推薦)

    java按字節(jié)截取帶有漢字的字符串的解法(推薦)

    下面小編就為大家?guī)?lái)一篇java按字節(jié)截取帶有漢字的字符串的解法(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-09-09
  • SpringBoot整合Thymeleaf的方法

    SpringBoot整合Thymeleaf的方法

    這篇文章主要介紹了SpringBoot整合Thymeleaf的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • java利用DFA算法實(shí)現(xiàn)敏感詞過(guò)濾功能

    java利用DFA算法實(shí)現(xiàn)敏感詞過(guò)濾功能

    在最近的開發(fā)中遇到了敏感詞過(guò)濾,便去網(wǎng)上查閱了很多敏感詞過(guò)濾的資料,在這里也和大家分享一下自己的理解。下面這篇文章主要給大家介紹了關(guān)于java利用DFA算法實(shí)現(xiàn)敏感詞過(guò)濾功能的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-06-06
  • Java實(shí)現(xiàn)簡(jiǎn)單的銀行管理系統(tǒng)的示例代碼

    Java實(shí)現(xiàn)簡(jiǎn)單的銀行管理系統(tǒng)的示例代碼

    這篇文章主要介紹了如何利用Java實(shí)現(xiàn)簡(jiǎn)單的銀行管理系統(tǒng),可以實(shí)現(xiàn)存款,取款,查詢等功能,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2022-09-09
  • Javaweb請(qǐng)求轉(zhuǎn)發(fā)及重定向?qū)崿F(xiàn)詳解

    Javaweb請(qǐng)求轉(zhuǎn)發(fā)及重定向?qū)崿F(xiàn)詳解

    這篇文章主要介紹了Javaweb請(qǐng)求轉(zhuǎn)發(fā)及重定向?qū)崿F(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 深入了解Java核心類庫(kù)--Math類

    深入了解Java核心類庫(kù)--Math類

    本文是小編最新給大家整理的關(guān)于Java中Math類常用方法的知識(shí),通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧,
    2021-07-07
  • java中的異步加載new Thread()方式

    java中的異步加載new Thread()方式

    這篇文章主要介紹了java中的異步加載new Thread()方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Java中垃圾回收器GC對(duì)吞吐量的影響測(cè)試

    Java中垃圾回收器GC對(duì)吞吐量的影響測(cè)試

    這篇文章主要介紹了Java中垃圾回收器GC對(duì)吞吐量的影響測(cè)試,本文算是一個(gè)對(duì)垃圾回收器GC的優(yōu)化文章,需要的朋友可以參考下
    2014-09-09

最新評(píng)論