以下内容转载自:https://my.oschina.net/u/3681868/blog/1813011
一, 引入Jar包:
mysql
mysql-connector-java
com.alibaba
druid-spring-boot-starter
1.1.9
二, 配置参数:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
druid:
one: #数据源1
url: jdbc:mysql://localhost:3306/test1?...
username: root
password: root
two: #数据源2
url: jdbc:mysql://localhost:3306/test2?...
username: root
password: root
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
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: true
wall:
config:
multi-statement-allow: true
(参数配置,可参考: https://gitee.com/wenshao/druid/tree/master/druid-spring-boot-starter)
三, 编写配置文件:
1, 定义数据源名称常量 :
package com.gy.fast.common.config.data;
/**
* 数据源名称
* @author geYang
* @date 2018-05-14
*/
public interface DataSourceNames {
String ONE = "ONE";
String TWO = "TWO";
}
2, 创建动态数据源:
package com.gy.fast.common.config.data;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.Map;
/**
* 动态数据源
* @author geYang
* @date 2018-05-14
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal contextHolder = new ThreadLocal<>();
/**
* 配置DataSource, defaultTargetDataSource为主数据库
*/
public DynamicDataSource(DataSource defaultTargetDataSource, Map
3, 动态数据源配置:
package com.gy.fast.common.config.data;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
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
@Primary
public DynamicDataSource dataSource(DataSource oneDataSource, DataSource twoDataSource) {
Map
4, 定义动态数据源注解:
package com.gy.fast.common.config.data;
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;
/**
* 多数据源注解
* @author geYang
* @date 2018-05-14
*/
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
String value() default DataSourceNames.ONE;
}
5, 设置数据源 AOP 代理:
package com.gy.fast.common.config.data;
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 geYang
* @date 2018-05-14
*/
@Aspect
@Component
public class DataSourceAspect implements Ordered {
protected Logger logger = LoggerFactory.getLogger(getClass());
/**
* 切点: 所有配置 DataSource 注解的方法
*/
@Pointcut("@annotation(com.gy.fast.common.config.data.DataSource)")
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("set datasource is " + ds.value());
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
logger.debug("clean datasource");
}
}
@Override
public int getOrder() {
return 1;
}
}
四, 修改启动文件:
package com.gy.fast;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Import;
import com.gy.fast.common.config.data.DynamicDataSourceConfig;
/**
* 动态数据源配置,需要将自有的配置依赖(DynamicDataSourceConfig),将原有的依赖去除(DataSourceAutoConfiguration)
* @author geYang
* @date 2018-05-15
*/
@Import({DynamicDataSourceConfig.class})
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
public class FastApplication {
public static void main(String[] args) {
SpringApplication.run(FastApplication.class, args);
}
}
五, 配置完成, 进行测试:
package com.gy.fast;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.gy.fast.common.config.data.DataSource;
import com.gy.fast.common.config.data.DataSourceNames;
import com.gy.fast.module.sys.entity.SysUser;
import com.gy.fast.module.sys.service.SysUserService;
/**
* 测试多数据源
* @author geYang
* @date 2018-05-15
*/
@Service
public class DataSourceTestService {
@Autowired
private SysUserService sysUserService;
public SysUser test1(Long userId){
return sysUserService.selectById(userId);
}
@DataSource(DataSourceNames.TWO)
public SysUser test2(Long userId){
return sysUserService.selectById(userId);
}
}
package com.gy.fast;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.gy.fast.module.sys.entity.SysUser;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DynamicDataSourceTest {
@Autowired
private DataSourceTestService dataSourceTestService;
@Test
public void test(){
// 数据源ONE
SysUser user1 = dataSourceTestService.test1(1L);
System.out.println(ToStringBuilder.reflectionToString(user1));
// 数据源TWO
SysUser user2 = dataSourceTestService.test2(1L);
System.out.println(ToStringBuilder.reflectionToString(user2));
// 数据源ONE
SysUser user3 = dataSourceTestService.test1(1L);
System.out.println(ToStringBuilder.reflectionToString(user3));
}
}