创建数据库和数据表
首先需要建立两个库进行测试,我这里使用的是master_test和slave_test两个库,
两个库都有一张同样的表,表名tuser
添加依赖
<!-- 添加druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- 添加aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
创建实体类
entity
/**
* User类
* @author Wang Guolong
* @version 1.0
* @date 2020/5/30 11:08 上午
*/
@Data
@Entity
public class Tuser implements Serializable {
private static final long serialVersionUID = 2470170238667716941L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="id", unique=true, nullable=false, precision=20)
private long id;
@Column(name="name", precision=50)
private String name;
}
repository
/**
* Tuser repository
* @author Wang Guolong
* @version 1.0
* @date 2020/5/30 11:07 上午
*/
public interface TuserRepository extends JpaRepository<Tuser, Integer> {
}
动态数据源配置
这里使用的数据源为druid,实现数据源之间的切换用@DataSource自定义注解,配置Aop进行切换 application.yml 配置文件。
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
wgl-master:
driverClassName: com.mysql.jdbc.Driver
username: root
password: password
url: jdbc:mysql://101.200.63.11:3306/master_test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8
wgl-slave:
driverClassName: com.mysql.jdbc.Driver
username: root
password: password
url: jdbc:mysql://101.200.63.11:3306/slave_test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8
多数据源配置类
/**
* 多数据源配置类
* @author Wang Guolong
* @version 1.0
* @date 2020/5/30 10:55 上午
*/
@Configuration
@Component
public class DynamicDataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.druid.wgl-master")
public DataSource wglMasterDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.druid.wgl-slave")
public DataSource wglSlaveDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public DynamicDataSource dataSource(DataSource wglMasterDataSource, DataSource wglSlaveDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("wgl-master",wglMasterDataSource);
targetDataSources.put("wgl-slave", wglSlaveDataSource);
return new DynamicDataSource(wglMasterDataSource, targetDataSources);
}
}
动态数据源切换类
/**
* 动态数据源切换类
* @author Wang Guolong
* @version 1.0
* @date 2020/5/30 10:57 上午
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
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();
}
}
自定义@DataSource注解
/**
* 自定义数据源选择注解
* @author Wang Guolong
* @version 1.0
* @date 2020/5/30 10:58 上午
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String name() default "";
}
Aop切面类配置
/**
* Aop切面类配置
* @author Wang Guolong
* @version 1.0
* @date 2020/5/30 11:01 上午
*/
@Aspect
@Component
public class DataSourceAspect {
@Pointcut("@annotation(com.wgl.cupid.annotation.DataSource)")
public void dataSourcePointCut() {
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
DataSource dataSource = method.getAnnotation(DataSource.class);
if(dataSource == null){
DynamicDataSource.setDataSource("wgl-master");
}else {
DynamicDataSource.setDataSource(dataSource.name());
}
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
}
}
}
启动配置注解信息,重要(不然运行会报错)
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@Import({DynamicDataSourceConfig.class})
public class CupidApplication {
public static void main(String[] args) {
SpringApplication.run(CupidApplication.class, args);
}
}
测试controller
/**
* 测试controller
* @author Wang Guolong
* @version 1.0
* @date 2020/5/30 11:04 上午
*/
@RestController
@RequestMapping
public class DynamicUserController {
@Autowired
private TuserRepository tuserRepository;
@GetMapping("/list/slave")
@DataSource(name = "wgl-slave")
public List<Tuser> listSlave(){
return tuserRepository.findAll();
}
@GetMapping("/list/master")
@DataSource(name = "wgl-master")
public List<Tuser> listMaster(){
return tuserRepository.findAll();
}
}
效果图
http://localhost:8080/list/master
http://localhost:8080/list/slave
参考资料
https://mp.weixin.qq.com/s/HNr97Fqonq3SZkJj21cDlg