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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>8.0.16</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--<exclusions>-->
<!--<exclusion>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-tomcat</artifactId>-->
<!--</exclusion>-->
<!--</exclusions>-->
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.22</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
项目结构图
yml文件
server:
port: 8086
mybatis:
mapperLocations: classpath*:mapper/*.xml
local:
host: localhost
port: 3306
taosEnable: false
spring:
datasource:
db1:
jdbc-url: jdbc:mysql://${local.host}:${local.port}/tb1?useUnicode=true&characterEncoding=gbk&autoReconnect=true&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnectForPools=true
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
#最小连接数
minIdle: 5
#最大连接数
maxActive: 500
#初始化连接数
initialSize: 5
#当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3
acquireIncrement: 5
#连接关闭时默认将所有未提交的操作回滚。Default: false
autoCommitOnClose: false
test-on-borrow: false
test-on-return: false
test-while-idle: true
validation-query: select 1;
validation-query-timeout: 5000
#最大空闲时间,30秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0
maxIdleTime: 30
#获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。
#如果设为true,那么在尝试 获取连接失败后该数据源将申明已断开并永久关闭。Default:false
breakAfterAcquireFailure: false
db2:
jdbc-url: jdbc:mysql://${local.host}:${local.port}/tb2?useUnicode=true&characterEncoding=gbk&autoReconnect=true&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnectForPools=true
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
#最小连接数
minIdle: 5
#配置SQL拦截
filters: stat
#最大连接数
maxActive: 500
#初始化连接数
initialSize: 5
#当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3
acquireIncrement: 5
#连接关闭时默认将所有未提交的操作回滚。Default: false
autoCommitOnClose: true
test-on-borrow: false
test-on-return: false
test-while-idle: true
validation-query: select 1;
validation-query-timeout: 5000
poolPreparedStatements: true
#最大空闲时间,30秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0
maxIdleTime: 30
#获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。
#如果设为true,那么在尝试 获取连接失败后该数据源将申明已断开并永久关闭。Default:false
breakAfterAcquireFailure: false
db3:
jdbc-url: jdbc:mysql://${local.host}:${local.port}/tb3?useUnicode=true&characterEncoding=gbk&autoReconnect=true&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnectForPools=true
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
#最小连接数
minIdle: 5
#配置SQL拦截
filters: stat
#最大连接数
maxActive: 500
#初始化连接数
initialSize: 5
#当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3
acquireIncrement: 5
#连接关闭时默认将所有未提交的操作回滚。Default: false
autoCommitOnClose: true
test-on-borrow: false
test-on-return: false
test-while-idle: true
validation-query: select 1;
validation-query-timeout: 5000
poolPreparedStatements: true
#最大空闲时间,30秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0
maxIdleTime: 30
#获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。
#如果设为true,那么在尝试 获取连接失败后该数据源将申明已断开并永久关闭。Default:false
breakAfterAcquireFailure: false
mapper.xml、dao、service、serviceImpl这些就不看了,跟单数据源一样
1、创建一个自定义注解
package com.example.demo.annotation;
import java.lang.annotation.*;
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface DataSource {
String value();
}
2、创建一个apo切面
package com.example.demo.config;
import com.example.demo.annotation.DataSource;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class DataSourceConfig {
@Before("@annotation(dataSource)")
public void beforeSwitchDataSource(DataSource dataSource) {
DynamicDataSource.changeDataSource(dataSource.value());
}
@After("@annotation(com.example.demo.annotation.DataSource)")
public void afterSwitchDataSource() {
DynamicDataSource.clearDataSource();
}
}
3、引入了配置信息之后,便是该说如何实现多数据源切换了。我们是通过实现AbstractRoutingDataSource
类的determineCurrentLookupKey
方法来实现数据源的动态路由,设置ThreadLocal
线程保护变量存储数据源key,确保线程间不受影响。
package com.example.demo.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* @author lazycece
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final Logger LOGGER = LoggerFactory.getLogger(DynamicDataSource.class);
private static final ThreadLocal<String> DATA_SOURCE_KEY = new ThreadLocal<>();
static void changeDataSource(String dataSourceKey) {
DATA_SOURCE_KEY.set(dataSourceKey);
}
static void clearDataSource() {
DATA_SOURCE_KEY.remove();
}
@Override
protected Object determineCurrentLookupKey() {
String key = DATA_SOURCE_KEY.get();
LOGGER.info("切换数据源为: {}", key);
return key;
}
}
4、java配置数据源
package com.example.demo.config;
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 javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class MultiDataSource {
public static final String TB1 = "tb1";
public static final String TB2 = "tb2";
public static final String TB3 = "tb3";
@Bean(name = MultiDataSource.TB1)
@ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSource tb1() {
return DataSourceBuilder.create().build();
}
@Bean(name = MultiDataSource.TB2)
@ConfigurationProperties(prefix = "spring.datasource.db2")
public DataSource tb2() {
return DataSourceBuilder.create().build();
}
@Bean(name = MultiDataSource.TB3)
@ConfigurationProperties(prefix = "spring.datasource.db3")
public DataSource tb3() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "dynamicDataSource")
public DynamicDataSource dataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setDefaultTargetDataSource(tb1());
Map<Object, Object> dataSourceMap = new HashMap<>(4);
dataSourceMap.put(TB1, tb1());
dataSourceMap.put(TB2, tb2());
dataSourceMap.put(TB3, tb3());
dynamicDataSource.setTargetDataSources(dataSourceMap);
return dynamicDataSource;
}
}
最最主要的是:在service的实现类上面加上注解,下面看我是怎么加的
完事了 ,直接启动,请求:
项目引入jar包图
这个是我自己经过网上东拼西凑,所得的结果,因为网上别人说的不怎么全,现在自己弄出来想记录一下。如果对你们有帮助,那我写这个就更加有意义了
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)