本帖最后由 ing 于 2020-11-18 02:28 编辑
项目地址:
https://gitee.com/liaoxuefeng/learn-java/raw/master/practices/Java%E6%95%99%E7%A8%8B/220.Spring%20Boot%E5%BC%80%E5%8F%91.1266265175882464/80.%E7%A6%81%E7%94%A8%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE.1282389045149729/springboot-multi-datasource.zip
——————————————————————————————————————
问题在这更新了
https://www.liaoxuefeng.com/discuss/1279869501571105/1381857000161314?page=1
——————————————————————————————————————
一共有创建两个HikariCP的DataSource,关联的key分别为"masterDataSource"和"slaveDataSource"
public class RoutingDataSourceConfiguration {
@Primary
@Bean
DataSource dataSource(@Autowired @Qualifier(RoutingDataSourceContext.MASTER_DATASOURCE) DataSource masterDataSource,
@Autowired @Qualifier(RoutingDataSourceContext.SLAVE_DATASOURCE) DataSource slaveDataSource) {
var ds = new RoutingDataSource();
ds.setTargetDataSources(Map.of(RoutingDataSourceContext.MASTER_DATASOURCE, masterDataSource,
RoutingDataSourceContext.SLAVE_DATASOURCE, slaveDataSource));
ds.setDefaultTargetDataSource(masterDataSource);
return ds;
}
@Bean
JdbcTemplate jdbcTemplate(@Autowired DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
DataSourceTransactionManager dataSourceTransactionManager(@Autowired DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
客户端代码
@Controller
public class UserController {
@RoutingWithSlave // <-- 指示在此方法中使用slave数据库,就是他,让我看懵了的注解,都不知道怎么做到的切换数据源
@GetMapping("/profile")
public ModelAndView profile(HttpSession session) {
...
}
}
@Retention(RUNTIME)
@Target(METHOD)
public @interface RoutingWithSlave {
}
自定义的注解 @RoutingWithSlave 的作用也只是调用 RoutingDataSourceContext 的构造方法向 ThreadLocal 储存了字符串 slaveDataSource
@Aspect
@Component
public class RoutingAspect {
@Around("@annotation(routingWithSlave)")
public Object routingWithDataSource(ProceedingJoinPoint joinPoint, RoutingWithSlave routingWithSlave)
throws Throwable {
try (RoutingDataSourceContext ctx = new RoutingDataSourceContext(RoutingDataSourceContext.SLAVE_DATASOURCE)) {
return joinPoint.proceed();
}
}
}
public class RoutingDataSourceContext implements AutoCloseable {
public static final String MASTER_DATASOURCE = "masterDataSource";
public static final String SLAVE_DATASOURCE = "slaveDataSource";
// holds data source key in thread local:
static final ThreadLocal<String> threadLocalDataSourceKey = new ThreadLocal<>();
public static String getDataSourceRoutingKey() {
String key = threadLocalDataSourceKey.get();
return key == null ? MASTER_DATASOURCE : key;
}
public RoutingDataSourceContext(String key) {
threadLocalDataSourceKey.set(key);
}
public void close() {
threadLocalDataSourceKey.remove();
}
}
当我访问 http://localhost:8080/profile 后,可以看到数据源已经切换为 HikariPool-2 不再是 HikariPool-1
2020-11-17 15:24:09.701 INFO 7056 --- [nio-8080-exec-7] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Starting...
2020-11-17 15:24:09.703 INFO 7056 --- [nio-8080-exec-7] com.zaxxer.hikari.pool.PoolBase : HikariPool-2 - Driver does not support get/set network timeout for connections. (feature not supported)
2020-11-17 15:24:09.706 INFO 7056 --- [nio-8080-exec-7] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Start completed.
自定义的注解 @RoutingWithSlave 是怎么做到的切换数据源? |