0


Springboot+Druid配置多数据源

Druid数据库多数据源

Spring的多数据源支持—AbstractRoutingDataSource,AbstractRoutingDataSource定义了抽象的determineCurrentLookupKey方法,子类实现此方法,来确定要使用的数据源

Druid 实现多数据源支持,核心是Overwrite AbstractRoutingDataSource 的 determineCurrentLookupKey 方法

publicabstractclassAbstractRoutingDataSourceextendsAbstractDataSourceimplementsInitializingBean{protectedDataSourcedetermineTargetDataSource(){Assert.notNull(this.resolvedDataSources,"DataSource router not initialized");Object lookupKey =determineCurrentLookupKey();DataSource dataSource =this.resolvedDataSources.get(lookupKey);if(dataSource ==null&&(this.lenientFallback || lookupKey ==null)){
            dataSource =this.resolvedDefaultDataSource;}if(dataSource ==null){thrownewIllegalStateException("Cannot determine target DataSource for                  lookup key ["+ lookupKey +"]");}return dataSource;}// 确定当前要使用的数据源protectedabstractObjectdetermineCurrentLookupKey();}

配置多数据源

以springboot框架为基础使用aop注解的方式依赖Druid配置多数据源

1.添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- aop注解实现aspectjweaver依赖 --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version></dependency><!-- mybatis-spring-boot-starter --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.3</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><scope>provided</scope></dependency>

2.配置Druid属性

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    first:
      url: jdbc:mysql://localhost:3306/***?useUnicode=true&characterEncoding=utf-                  8&serverTimezone=UTC
      username: root
      password: *****
    second:
      enable: true
      url: jdbc:mysql://localhost:3306/***?useUnicode=true&characterEncoding=utf-                 8&serverTimezone=UTC
      username: root
      password: *****
    druid:
      # 初始连接数
      initialSize: 5
      # 最小连接池数量
      minIdle: 10
      # 最大连接池数量
      maxActive: 20
      # 配置获取连接等待超时的时间
      maxWait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      minEvictableIdleTimeMillis: 300000
      # 配置一个连接在池中最大生存的时间,单位是毫秒
      maxEvictableIdleTimeMillis: 900000
      # 配置检测连接是否有效
      validationQuery: SELECT 1 FROM DUAL
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      webStatFilter:
        enabled: true
      statViewServlet:
        enabled: true
        # 控制台管理用户名和密码
        login-username: admin
        login-password: 123456
      #配置监控统计拦截的filters:stat:监控统计、self4j(使用log4j的记得导入log4j的依赖):日志记录、          wall:防御sql注入 此处配置不能遗漏服务sql监控台不能监控sql
      filters: stat,wall,log4j2
      filter:
        stat:
          enabled: true
          # 慢SQL记录
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: true
        wall:
          enabled: true
          config:
            multi-statement-allow: true

3.配置动态数据源

继承AbstractRoutingDataSource重写determineCurrentLookupKey()方法

/**
 * 动态数据源
 */publicclassDynamicDatesourceextendsAbstractRoutingDataSource{publicDynamicDatesource(DataSource dataSource,HashMap<Object,Object> map){super.setDefaultTargetDataSource(dataSource);super.setTargetDataSources(map);super.afterPropertiesSet();}/**
     * 获取key指定数据源
     * @return
     */@OverrideprotectedObjectdetermineCurrentLookupKey(){returnDynamicDateSourceCut.getLocal();}}

配置数据源

//配置数据源
@Configuration
public class DruidConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.first")
    public DataSource firstDataSource(DruidSourceProperties druidSourceProperties){

        return druidSourceProperties.dataSource(new DruidDataSourceWrapper());
    }
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.second")
    @ConditionalOnProperty(prefix ="spring.datasource.second",name ="enable",havingValue = "true")
    public DataSource secondDataSource(DruidSourceProperties druidSourceProperties){
        return druidSourceProperties.dataSource(new DruidDataSourceWrapper());
    }
    @Bean
    @Primary//在多数据源的时候,使用@Primary注解用于指定其中一个作为主数据源
    public DynamicDatesource setDymaicDatesource(DataSource firstDataSource){
        HashMap<Object, Object> map = new HashMap<>();
        map.put(DateSourceType.FIRST.name(),firstDataSource);
        setDataSource(map,DateSourceType.SECOND.name(),"secondDataSource");
        return new DynamicDatesource(firstDataSource,map);
    }
    /**
     * 设置数据源
     *
     * @param targetDataSources 备选数据源集合
     * @param sourceName 数据源名称
     * @param beanName bean名称
     */
    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName,         String beanName){
        try {
            DataSource dataSource = SpringUtils.getBean(beanName);
            targetDataSources.put(sourceName, dataSource);
        } catch (Exception e){

        }
    }
}

4.配置数据源切换

packagecom.example.springboot.data;/**
*数据源切换 保存每个数据源指定的lookupKey
*/publicclassDynamicDateSourceCut{/**
     * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
     *  所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
     */privatestaticThreadLocal<String> threadLocal=newThreadLocal<>();/**
     * 设置数据源的变量
     */publicstaticvoidsetLocal(String local){
        threadLocal.set(local);}/**
     * 获得数据源的变量
     */publicstaticStringgetLocal(){return threadLocal.get();}/**
     * 清空数据源变量
     */publicstaticvoidclearLocl(){
        threadLocal.remove();}}

5.定义aop切面实现

/**
 * 定义数据源切面
 */@Aspect@ComponentpublicclassDateSourceAspect{privatestaticfinalLogger log=LoggerFactory.getLogger(DateSourceAspect.class);/**
     * 定义切点  使用注解
     * @within类注解
     * @annotation方法注解
     */@Pointcut("@annotation(com.example.springboot.aspect.DateSource)"+"||@within(com.example.springboot.aspect.DateSource)")publicvoidPintCut(){}/**
     * 通知使用环绕的通知方法
     */@Around("PintCut()")publicObjectResovePoint(ProceedingJoinPoint point)throwsThrowable{//获取注解DateSource dateSource =getDateSource(point);if(dateSource!=null){DynamicDateSourceCut.setLocal(dateSource.value().name());}try{//执行方法return point.proceed();}finally{// 销毁数据源 在执行方法之后DynamicDateSourceCut.clearLocl();}}/**
     * 获取注解
     */protectedDateSourcegetDateSource(ProceedingJoinPoint point){MethodSignature signature =(MethodSignature) point.getSignature();//获取方法或方法类型上的注解DateSource annotation;//获取class类型上注解
        annotation=AnnotationUtils.findAnnotation(signature.getDeclaringType(),DateSource.class);if(annotation==null){
            annotation =AnnotationUtils.findAnnotation(signature.getMethod(),DateSource.class);}return annotation;}}

定义的注解和注解值

/**
 * 定义注解
 */@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic@interfaceDateSource{DateSourceTypevalue()defaultDateSourceType.FIRST;}/**
*使用枚举定义注解的值
*/publicenumDateSourceType{//默认数据库FIRST,SECOND;}
标签: spring boot spring java

本文转载自: https://blog.csdn.net/Mr_ming_a_probie/article/details/127920120
版权归原作者 Mr_ming_a_probie 所有, 如有侵权,请联系我们删除。

“Springboot+Druid配置多数据源”的评论:

还没有评论