Spirngboot 2.X 整合mybatis-plus +druid 多数据源的实现

首先加入依赖:

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

        <!--MySQL 连接驱动依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--mybatis-plus数据持久层-->
        <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>3.3.1</version>
        </dependency>
  <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>
  <!--druid数据连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.22</version>
        </dependency>
 <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>

在配置文件增加下面配置:

spring:
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  aop:
    auto: true
    proxy-target-class: true
  datasource:
    druid:
      db1:
        url: jdbc:mysql://ip:端口/db1?useSSL=false&characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useUnicode=true&rewriteBatchedStatements=true
        username: ****#mysql账号
        password: ***#mysql密码
        driver-class-name: com.mysql.cj.jdbc.Driver
        initialSize: 5
        minIdle: 5
        maxActive: 20
      db2:
        url: jdbc:mysql://****/db2?useSSL=false&characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useUnicode=true&rewriteBatchedStatements=true
        username: ****#mysql账号
        password: ***#mysql密码
        driver-class-name: com.mysql.cj.jdbc.Driver
        initialSize: 5
        minIdle: 5
        maxActive: 20


mybatis:
  type-aliases-package: com.*.*.entity #实体映射类包的位置
  configuration:
    # 驼峰下划线转换
    map-underscore-to-camel-case: true
  mapper-locations: classpath*:/mapper/**/*.xml

#设置druid后台访问白名单
druid:
  config:
    white-list: 127.0.0.1,loclhost

下面配置DruidConfig

import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Value;
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.List;

@Configuration
public class DruidConfig {

  @Value("#{'${druid.config.white-list}'.split(',')}")
  private List<String> whitelist;
  /**
   * 注册ServletRegistrationBean
   *
   * @return
   */
  @Bean
  public ServletRegistrationBean druidServlet() {
    ServletRegistrationBean reg = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
    // IP白名单
    for (String ip : whitelist) {
      reg.addInitParameter("allow", ip);
    }
    // IP黑名单(共同存在时,deny优先于allow)
    //        reg.addInitParameter("deny","127.0.0.1");
    // 控制台管理用户
    reg.addInitParameter("loginUsername", "**");//设置登陆账号
    reg.addInitParameter("loginPassword", "***");//设置登陆密码
    // 是否能够重置数据
    reg.addInitParameter("resetEnable", "false");
    return reg;
  }

  /**
   * 注册FilterRegistrationBean
   *
   * @return
   */
  @Bean
  public FilterRegistrationBean filterRegistrationBean() {
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
    filterRegistrationBean.setFilter(new WebStatFilter());
    filterRegistrationBean.addUrlPatterns("/*");
    filterRegistrationBean.addInitParameter(
        "exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
    filterRegistrationBean.addInitParameter("profileEnable", "true");
    filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE");
    filterRegistrationBean.addInitParameter("principalSessionName", "USER_SESSION");
    filterRegistrationBean.addInitParameter("DruidWebStatFilter", "/*");
    return filterRegistrationBean;
  }
}

定义数据源枚举

public enum DBTYPE {
    db1("db1"),
    db2("db2"),
    db3("db3");

    private String value;

    private DBTYPE(String value) {
        this.value = value;
    }

    public String getValue() {
        return this.value;
    }
}

定义数据源上下文



public class DbContextHolder {
    private static final ThreadLocal contextHolder = new ThreadLocal();

    public DbContextHolder() {
    }

    public static void setDbType(DBTYPE dbTypeEnum) {
        contextHolder.set(dbTypeEnum.getValue());
    }

    public static String getDbType() {
        return (String)contextHolder.get();
    }

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

动态数据源设置

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

/**
 * @program: common
 * @description: 动态数据源
 * @author: linwl
 * @create: 2020-06-20 15:33
 **/
public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    public Object determineCurrentLookupKey()
    {
        return DbContextHolder.getDbType();
    }
}

定义动态数据源切换类

import db.DBTYPE;
import db.DbContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(value = -100)
@Slf4j
@Aspect
public class DataSourceSwitchAspect {
  //数据源1切点
  @Pointcut("execution(* com.*.mapper.db1..*.*(..))")
  public void db1Aspect() {}
  //数据源2切点
  @Pointcut("execution(* com.*.mapper.db2..*.*(..))")
  public void db2Aspect() {}
  //数据源3切点
  @Pointcut("execution(* com.*.mapper.db3..*.*(..))")
  public void db3Aspect() {}

  @Before("db1Aspect()")
  public void getdb1() {
    log.info("切换到db1 数据源...");
    DbContextHolder.setDbType(DBTYPE.db1);
  }

  @Before("db2Aspect()")
  public void getdb2() {
    log.info("切换到db2 数据源...");
    DbContextHolder.setDbType(DBTYPE.db2);
  }

  @Before("db3Aspect()")
  public void getdb3() {
    log.info("切换到db3 数据源...");
    DbContextHolder.setDbType(DBTYPE.db3);
  }

  @After("db1Aspect()")
  public void romvedb1() {
    log.info("移除数据源");
    DbContextHolder.clearDbType();
  }

  @After("db2Aspect()")
  public void romvedb2() {
    log.info("移除数据源");
    DbContextHolder.clearDbType();
  }

  @After("db3Aspect()")
  public void romvedb3() {
    log.info("移除数据源");
    DbContextHolder.clearDbType();
  }
}

前期的配置基本完成了,接下来就是要进入MybatisPlus的配置了
配置如下:

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import db.DBTYPE;
import db.DynamicDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.mapping.DatabaseIdProvider;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.MybatisProperties;
import org.springframework.beans.factory.annotation.Autowired;
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.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

@Configuration
@MapperScan("com.***.mapper")
@EnableTransactionManagement
@Slf4j
public class MybatisPlusConfig {

  @Autowired private MybatisProperties properties;

  private ResourceLoader resourceLoader = new DefaultResourceLoader();

  @Autowired(required = false)
  private DatabaseIdProvider databaseIdProvider;

  /**
   * mybatis-plus分页插件<br>
   * 文档:http://mp.baomidou.com<br>
   */
  @Bean
  public PaginationInterceptor paginationInterceptor() {
    PaginationInterceptor page = new PaginationInterceptor();
    page.setDbType(DbType.MYSQL);
    return new PaginationInterceptor();
  }

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

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

  //  @Bean(name = "db3")
  //  @ConfigurationProperties(prefix = "spring.datasource.druid.db3")
  //  public DataSource db3() {
  //    return DruidDataSourceBuilder.create().build();
  //  }

  /**
   * 动态数据源配置
   *
   * @return
   */
  @Bean
  @Primary
  public DataSource multipleDataSource(
      @Qualifier("db1") DataSource db1, @Qualifier("db2") DataSource db2) {
    DynamicDataSource dynamicDataSource = new DynamicDataSource();
    Map<Object, Object> targetDataSources = new HashMap<>(3);
    targetDataSources.put(DBTYPE.db1.getValue(), db1);
    targetDataSources.put(DBTYPE.db2.getValue(), db2);
    dynamicDataSource.setTargetDataSources(targetDataSources);
    dynamicDataSource.setDefaultTargetDataSource(db1);
    return dynamicDataSource;
  }

  @Bean("sqlSessionFactory")
  public SqlSessionFactory sqlSessionFactory() throws Exception {
    try {
      MybatisSqlSessionFactoryBean mybatisPlus = new MybatisSqlSessionFactoryBean();
      mybatisPlus.setDataSource(multipleDataSource(db1(), db2()));
      if (StringUtils.hasText(this.properties.getConfigLocation())) {
        mybatisPlus.setConfigLocation(
            this.resourceLoader.getResource(this.properties.getConfigLocation()));
      }
      mybatisPlus.setPlugins(paginationInterceptor());
      MybatisConfiguration mc = new MybatisConfiguration();
      mc.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
      mybatisPlus.setConfiguration(mc);
      if (this.databaseIdProvider != null) {
        mybatisPlus.setDatabaseIdProvider(this.databaseIdProvider);
      }
      if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
        mybatisPlus.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
      }
      if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
        mybatisPlus.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
      }
      if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
        mybatisPlus.setMapperLocations(this.properties.resolveMapperLocations());
      }
      return mybatisPlus.getObject();
    } catch (Exception e) {
      log.error(MessageFormat.format("初始化Mybatis配置异常:{0}!", e.getMessage()));
      throw e;
    }
  }
}

多数据源动态切换就大功告成!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Top_雨夜聆风丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值