springboot多数据源配置

jar包引入

<!-- mysql连接驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>
<!-- 连接池 -->
<dependency> 
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.13</version>
</dependency>

配置文件

application.yml的配置

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    druid:
      one: #默认数据源   连接test库   
        url: jdbc:mysql://127.0.0.1:3306/test?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
        username: test
        password: 123456
      two: #数据源二   连接admin库   
        url: jdbc:mysql://127.0.0.1:3306/admin?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
        username: admin
        password: 123456
      initial-size: 10
      max-active: 100
      min-idle: 10
      max-wait: 60000
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 20
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      #Oracle需要打开注释
      #validation-query: SELECT 1 FROM DUAL
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      stat-view-servlet:
        #enabled: true
        #url-pattern: /druid/*
        login-username: admin
        login-password: admin
      filter:
        stat:
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: false
        wall:
          config:
            multi-statement-allow: true

定义数据源的名称

package com.bds.common.dataSource;

/**
 * 数据源名称
 */
public interface DataSourceNames {
    String ONE = "test";//对应application.yml中的数据源one(默认数据源)
    String TWO = "admin";//对应application.yml中的数据源two
    //String THREE = "root";//对应application.yml中的数据源three
}

创建动态数据源

package com.bds.common.dataSource;


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

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

/**
 * 动态数据源
 * @author 
 * @date
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    /**
     * 配置DataSource, defaultTargetDataSource为主数据库
     */
    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }

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

    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
    }

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

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

}

动态数据源配置

package com.bds.common.dataSource;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.bds.common.utils.JspyptUtils;

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 javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * 配置多数据源
 * @author geYang
 * @date 2018-05-14
 */
@Configuration
public class DynamicDataSourceConfig {
    
    /**
     * 创建 DataSource Bean
     * */	
    @Bean
    @ConfigurationProperties("spring.datasource.druid.one")
    public DataSource oneDataSource(){
        DataSource dataSource = DruidDataSourceBuilder.create().build();
        return dataSource;
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.two")
    public DataSource twoDataSource(){
        DataSource dataSource = DruidDataSourceBuilder.create().build();
        return dataSource;
    }
     /**
     * 如果还有数据源,在这继续添加 DataSource Bean
     * */
    //@Bean
    //@ConfigurationProperties("spring.datasource.druid.three")//application中的名为three的数据源连接
    //public DataSource threeDataSource(){
    //    DataSource dataSource = DruidDataSourceBuilder.create().build();
    //    return dataSource;
    //}

    
    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSource oneDataSource, DataSource twoDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>(2);
        targetDataSources.put(DataSourceNames.ONE, oneDataSource);
        targetDataSources.put(DataSourceNames.TWO, twoDataSource);
        // 还有数据源,在targetDataSources中继续添加
        //targetDataSources.put(DataSourceNames.THREE, twoDataSource);
        System.out.println("DataSources:" + targetDataSources);
        return new DynamicDataSource(oneDataSource, targetDataSources);
    }
}

多数据源定义注解和设置aop代理

定义注解

package com.bds.common.dataSource;

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;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

/**
 * 多数据源注解
 * @author 
 * @date 
 */
@SuppressWarnings("unused")
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
	/**
	* 默认数据源为one,可修改为其他数据源为默认数据源
	*/
    String value() default DataSourceNames.ONE;//默认值
}

aop代理

package com.bds.common.dataSource;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

/**
 * 数据源AOP切面处理
 * @author 
 * @date 
 */
@Aspect
@Component
public class DataSourceAspect implements Ordered {
    protected Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * 切点: 所有配置 DataSource 注解的方法
     */
    @Pointcut("@annotation(com.bds.common.dataSource.DataSource)")//修改为自己DataSource.java所在路径的包
    public void dataSourcePointCut() {}

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        DataSource ds = method.getAnnotation(DataSource.class);
        // 通过判断 DataSource 中的值来判断当前方法应用哪个数据源
        DynamicDataSource.setDataSource(ds.value());
       // System.out.println("当前数据源: " + ds.value());
        logger.debug("***************");
        logger.debug("set datasource is " + ds.value());
        try {
            return point.proceed();
        } finally {
            DynamicDataSource.clearDataSource();
            logger.debug("clean datasource");
        }
    }
    @Override
    public int getOrder() {
        return 1;
    }
}

修改启动文件

package com.bds;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Import;
import org.springframework.web.bind.annotation.CrossOrigin;
import com.bds.common.dataSource.DynamicDataSourceConfig;


@Import({DynamicDataSourceConfig.class})//导入自己配置的数据源
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})//多数据源配置,跳过框架自带的数据库引用
@CrossOrigin//跨域
public class AdminApplication extends SpringBootServletInitializer{

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

使用测试

因为已经配置好了多数据源注解,在实际应用场景中只需要通过注解来实现数据源的切换即可实现动态数据源。

使用默认数据源:不需要做任何处理

@Mapper
public interface LcAreaIndexDao extends BaseMapper<LcAreaIndexEntity> {
	List<LcAreaIndexEntity> queryList(Map<String, Object> map);
	int queryListNum(Map<String, Object> map);
}

使用动态数据源:在dao层的方法上添加注解

@Mapper
public interface LcAreaIndexDao extends BaseMapper<LcAreaIndexEntity> {
	@DataSource(DataSourceNames.TWO)
	List<LcAreaIndexEntity> queryList(Map<String, Object> map);
	@DataSource(DataSourceNames.TWO)
	int queryListNum(Map<String, Object> map);
}

以上就已经实现了动态数据源的配置。
@DataSource注解也可以加在service层的方法上使用,与dao层是一致的。

本文转载SpringBoot–Druid多数据源配置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值