SpringBoot多数据源动态切换

        本文环境是SpringBoot + Spring + Mybatis Plus

      思路 :

              1.配置多数据源

              2.使用注解来标记目标数据源

              3.使用AOP来动态切换数据源

       1.yml:

application.yml

#app
server:
    port: 8085
#spring
spring:
  profiles:
    active: dev
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    channel:
      name: bole_channel
      # druid相关配置
      # 监控统计拦截的filters
      filters: stat
      # -log4j
      # -wall
      # 配置初始化大小/最小/最大
      initial-size: 1
      min-idle: 1
      max-active: 20
      # 获取连接等待超时时间
      max-wait: 60000
      # 间隔多久进行一次检测,检测需要关闭的空闲连接
      time-between-eviction-runs-millis: 60000
      # 一个连接在池中最小生存的时间
      min-evictable-idle-time-millis: 300000
      validation-query: SELECT 'x'
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      # 打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
      pool-prepared-statements: false
      max-pool-prepared-statement-per-connection-size: 20
      driver-class-name: com.mysql.jdbc.Driver
    qlm:
      name: bole_qlm
      # druid相关配置
      # 监控统计拦截的filters
      filters: stat
      # -log4j
      # -wall
      # 配置初始化大小/最小/最大
      initial-size: 1
      min-idle: 1
      max-active: 20
      # 获取连接等待超时时间
      max-wait: 60000
      # 间隔多久进行一次检测,检测需要关闭的空闲连接
      time-between-eviction-runs-millis: 60000
      # 一个连接在池中最小生存的时间
      min-evictable-idle-time-millis: 300000
      validation-query: SELECT 'x'
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      # 打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
      pool-prepared-statements: false
      max-pool-prepared-statement-per-connection-size: 20
      driver-class-name: com.mysql.jdbc.Driver


#mybatis
mybatis-plus:
  # 如果是放在src/main/java目录下 classpath:/com/yourpackage/*/dao/*Mapper.xml
  # 如果是放在resource目录 classpath:/dao/*Mapper.xml
  mapper-locations: classpath*:/mapper/*Mapper.xml
  #实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.agent_web.api.entity
  typeEnumsPackage: com.agent_web.api.enums
  global-config:
    db-config:
    #主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
      id-type: AUTO
    # 字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
      field-strategy: not_empty
    # 驼峰下划线转换
      column-underline: true
    # mp2.3+ 全局表前缀 mp_
    # table-prefix: mp_
    # 刷新mapper 调试神器
    # refresh-dao: true
    # 数据库大写下划线转换
    # capital-mode: true
    # Sequence序列接口实现类配置
    # key-generator: com.baomidou.mybatisplus.incrementer.OracleKeyGenerator
    #逻辑删除配置(下面3个配置)
      logic-delete-value: 1
      logic-not-delete-value: 0
    # sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector
      db-type: mysql
    refresh: true

    # sql-injector: com.baomidou.mybatisplus.core.injector.ISqlInjector
    # 自定义填充策略接口实现
    # meta-object-handler: com.baomidou.springboot.MyMetaObjectHandler
  configuration:
    # 配置返回数据库(column下划线命名&&返回java实体是驼峰命名),自动匹配无需as(没开启这个,SQL需要写as: select user_id as userId)
    map-underscore-to-camel-case: true
    cache-enabled: false
#  type-enums-package: com.shengya.service.bean.enums

application-dev.xml

spring:
# 数据源
  datasource:
    channel:
      url: jdbc:mysql://localhost:3306/channel?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull
      username: admin    
      password: 111111
    qlm:
      url: jdbc:mysql://localhost:3306/qlm?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull
      username: admin
      password: 111111


      Config:

        继承Spring的AbstractRoutingDataSource类,该类相当于一个DataSource路由,可以根据key值自动切换对应数据源

package com.agent_web.api.config;

import com.agent_web.api.utils.DataSourceHolder;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * @author wise
 * @version 2.0.0
 * @createdate 2018-07-23 15:42.
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceHolder.getDataSource();
    }
}

      多数据源初始化:

package com.agent_web.api.config;

import com.agent_web.api.enums.CommonEnum;
import com.alibaba.druid.pool.DruidDataSource;
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.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;

/** 多数据配置(初始化)
 * @author wise
 * @createdate 2018-07-23 15:41.
 */
@Configuration
public class MultipleDataSourceConfig {

    @Bean(name = "dataSourceChannel")
    @ConfigurationProperties(prefix = "spring.datasource.channel")
    public DataSource channelDataSource(){
        return new DruidDataSource();
    }

    @Bean(name = "dataSourceQlm")
    @ConfigurationProperties(prefix = "spring.datasource.qlm")
    public DataSource qlmDataSource(){
        return new DruidDataSource();
    }


    @Primary
    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        //配置默认数据源
        dynamicDataSource.setDefaultTargetDataSource(channelDataSource());

        //初始化数据源
        HashMap<Object, Object> dataSourceMap = new HashMap();
        dataSourceMap.put(CommonEnum.DataSourceType.CHANNEL.name(),channelDataSource());
        dataSourceMap.put(CommonEnum.DataSourceType.QLM.name(),qlmDataSource());
        dynamicDataSource.setTargetDataSources(dataSourceMap);
        return dynamicDataSource;
    }

    /**
     * 配置@Transactional注解事务
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }
}

      2.注解:@DataSource

package com.agent_web.api.annotation;

import com.agent_web.api.enums.CommonEnum;

import java.lang.annotation.*;

/**
 * @author wise
 * @createdate 2018-08-23 11:29.
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {

    CommonEnum.DataSourceType value() default CommonEnum.DataSourceType.CHANNEL;

}

CommonEnum:

public enum DataSourceType{
        CHANNEL,QLM
}

      3.使用AOP来实现数据源动态切换

package com.agent_web.api.aop;

import com.agent_web.api.annotation.DataSource;
import com.agent_web.api.enums.CommonEnum;
import com.agent_web.api.utils.DataSourceHolder;
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.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author wise
 * @createdate 2018-07-23 17:40.
 */
@Component
@Aspect
public class DataSourceAspect {

    /**  设定切面
     * @author  wise
     * @date    2018/7/23 0027  17:42
     * @param
     * @return  void
     */
    @Pointcut("@annotation(com.agent_web.api.annotation.DataSource)")
    private void pointcut() {

    }

    /**  在执行方法体之前切换数据源
     * @author  wise
     * @date    2018/7/23 0027  17:45
     * @param point
     * @return  void
     */
    @Before("pointcut()&&@annotation(com.agent_web.api.annotation.DataSource)")
    public void before (JoinPoint point) {
        try {
            //获取默认数据源
            CommonEnum.DataSourceType dataSourceType = CommonEnum.DataSourceType.CHANNEL;
            String methodName = point.getSignature().getName();
            //获取参数类型
            Class[] parameterTypes = ((MethodSignature) point.getSignature()).getParameterTypes();
            Method method = point.getTarget().getClass().getMethod(methodName, parameterTypes);
            //获取方法上的注解
            DataSource methodAnnotation = method.getAnnotation(DataSource.class);
            if (methodAnnotation != null && methodAnnotation.value() != null) {
                //设置目标数据源
                dataSourceType = methodAnnotation.value();
            }
            //切换数据源
            DataSourceHolder.setDataSource(dataSourceType.name());
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    /**  清除数据源
     * @author  wise
     * @date    2018/7/23 0027  17:50
     * @param point
     * @return  void
     */
    @After("pointcut()&&@annotation(com.agent_web.api.annotation.DataSource)")
    public void after(JoinPoint point){
        DataSourceHolder.clearDataSource();
    }

}

DataSourceHolder:

     这里使用ThreadLocal来存储数据源,保证当前线程的数据源是隔离状态的

package com.agent_web.api.utils;

import lombok.extern.log4j.Log4j2;

/** 数据源切换类
 * @author wise
 * @createdate 2018-07-23 17:24.
 */
@Log4j2
public class DataSourceHolder {


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

    public static void setDataSource(String dbType){
        log.info("切换数据源: {}" ,dbType);
        contextHolder.set(dbType);
    }

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

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

      其它:

        因为我们要使用自定义的数据观配置,所以需要关掉SpringBoot的自动数据源配置

        exclude = DataSourceAutoConfiguration.class

package com.agent_web.api;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class AgentWebApplication {

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

      总结:

        在SpringMVC使用过动态数据源切换的小伙伴应该发现,其实都是一样的,只不过是SpringBoot的配置方式发生了改变而已,以前我们在XML中配置多数据源,现在换到了yml中,以上所有代码都经过了测试,如有问题,请您私信我

版权声明:本文为博主原创文章,转载请注明出处(https://blog.csdn.net/F1004145107/article/details/82022683)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring Boot是一个用于简化Spring应用开发的框架,可以方便地实现多数据源动态切换功能。 在Spring Boot中,通过配置多个数据源bean,可以实现多数据源的使用。首先,在application.properties或application.yml文件中配置多个数据源的相关属性,例如数据库连接信息、驱动程序等。然后,在Spring Boot的配置类中,通过@Bean注解将数据源bean配置到Spring容器中。 为了实现动态切换数据源,可以使用ThreadLocal或者AOP进行数据源的切换。首先,可以定义一个DataSourceContextHolder类,使用ThreadLocal来存储当前线程使用的数据源标识。然后,可以在需要切换数据源的地方,通过调用DataSourceContextHolder的setDataSourceKey方法,设置当前线程使用的数据源标识。在数据访问层的代码中,可以通过调用DataSourceContextHolder的getDataSourceKey方法获取当前线程使用的数据源标识,然后根据该标识来获取对应的数据源bean。 除了使用ThreadLocal,还可以使用AOP来实现数据源的切换。可以定义一个切面,通过在切面中获取注解或者方法名来确定使用的数据源,然后通过切换数据源的方式来实现动态切换。 通过以上的方式,就可以实现Spring Boot的多数据源动态切换功能。不同的数据源可以根据自己的需求和业务场景进行配置和使用,提高系统的扩展性和灵活性。 ### 回答2: Spring Boot提供了方便的配置和集成多数据源,并且支持动态切换数据源。下面将通过一个简单的示例来说明如何在Spring Boot中实现多数据源动态切换。 首先,在pom.xml文件中添加Spring Boot和数据源相关的依赖项,比如Spring Boot Starter、MyBatis、Druid等。然后,在application.properties文件中配置数据源的相关信息,包括数据库的URL、用户名、密码等。 接下来,创建多个数据源的配置类,通过@Configuration注解将其标记为配置类,并使用@Bean注解来创建数据源对象。在创建数据源对象时,可以使用DruidDataSource或者其他适配的数据源类。 在创建数据源配置类时,可以使用@Primary注解来指定一个主数据源,该主数据源将作为默认数据源使用。对于其他数据源,可以使用@Qualifier注解进行标识。 然后,在创建MyBatis的SqlSessionFactoryBean时,使用@MapperScan注解来扫描并加载Mapper接口。在其中配置数据源,可以通过注入的方式获取数据源对象,并将其设置到SqlSessionFactoryBean中。 最后,在需要切换数据源的地方,可以通过使用AOP切面和动态切换数据源的方式来实现。可以创建一个DataSourceAspect切面类,在其中定义切点和通知,通过在方法上添加@DataSource注解来指定要切换的数据源。在通知方法中,通过读取注解上的参数来确定要切换的数据源,并将其设置到ThreadLocal变量中。 总结起来,Spring Boot多数据源动态切换的步骤包括添加依赖项、配置数据源、创建数据源配置类、配置MyBatis的SqlSessionFactoryBean以及使用AOP实现动态切换数据源。通过这些步骤,我们可以在Spring Boot中轻松实现多数据源动态切换。 ### 回答3: 在Spring Boot中实现多数据源动态切换可以通过以下步骤实现: 1. 配置数据源:在application.properties或yml文件中配置多个数据源的连接信息,每个数据源都有独立的数据源配置属性。 2. 创建数据源工厂:使用Spring的Bean注解创建多个数据源对象,并分别设置其相关属性。 3. 创建数据源路由器:创建一个数据源路由器类,该类包含一个ThreadLocal变量,用于保存当前线程所使用的数据源标识。 4. 创建数据源切换注解:使用自定义注解方式,通过在Service层的方法上加上注解,来选择对应的数据源。 5. 创建切面:使用AOP的方式,在方法执行前获取选择的数据源标识,并存入数据源路由器的ThreadLocal变量中。 6. 创建数据源切换切入点:在切面中设置一个切入点,用于匹配加上数据源切换注解的方法。 7. 配置数据源切面:使用Spring的Bean注解配置切面类。 8. 启动类中配置数据源切换:在启动类中添加@EnableAspectJAutoProxy注解来开启AOP,同时使用@Import注解引入切面类。 9. 使用数据源切换注解:在Service层的方法上加上数据源切换注解,指定使用哪个数据源。 通过以上步骤,就可以在使用Spring Boot时实现多数据源动态切换。在需要切换数据源的地方,只需要使用自定义的注解来指定数据源,切换的过程由切面和数据源路由器来完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值