《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
driver-class-name: com.mysql.jdbc.Driver
hikari:
pool-name: HikariCP
auto-commit: false
…
ro-datasource:
jdbc-url: jdbc:mysql://localhost/test
username: ro
password: ro_password
driver-class-name: com.mysql.jdbc.Driver
hikari:
pool-name: HikariCP
auto-commit: false
…
复制代码
在开发环境下,没有必要配置主从数据库。只需要给数据库设置两个用户,一个rw
具有读写权限,一个ro
只有 SELECT 权限,这样就模拟了生产环境下对主从数据库的读写分离。
在 SpringBoot 的配置代码中,我们初始化两个数据源:
@SpringBootApplication
public class MySpringBootApplication {
/**
- Master data source.
*/
@Bean(“masterDataSource”)
@ConfigurationProperties(prefix = “spring.datasource”)
DataSource masterDataSource() {
logger.info(“create master datasource…”);
return DataSourceBuilder.create().build();
}
/**
- Slave (read only) data source.
*/
@Bean(“slaveDataSource”)
@ConfigurationProperties(prefix = “spring.ro-datasource”)
DataSource slaveDataSource() {
logger.info(“create slave datasource…”);
return DataSourceBuilder.create().build();
}
…
}
复制代码
第二步:编写 RoutingDataSource
然后,我们用 Spring 内置的 RoutingDataSource,把两个真实的数据源代理为一个动态数据源:
public class RoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return “masterDataSource”;
}
}
复制代码
对这个RoutingDataSource
,需要在 SpringBoot 中配置好并设置为主数据源:
@SpringBootApplication
public class MySpringBootApplication {
@Bean
@Primary
DataSource primaryDataSource(
@Autowired @Qualifier(“masterDataSource”) DataSource masterDataSource,
@Autowired @Qualifier(“slaveDataSource”) DataSource slaveDataSource
) {
logger.info(“create routing datasource…”);
Map<Object, Object> map = new HashMap<>();
map.put(“masterDataSource”, masterDataSource);
map.put(“slaveDataSource”, slaveDataSource);
RoutingDataSource routing = new RoutingDataSource();
routing.setTargetDataSources(map);
routing.setDefaultTargetDataSource(masterDataSource);
return routing;
}
…
}
复制代码
现在,RoutingDataSource 配置好了,但是,路由的选择是写死的,即永远返回"masterDataSource"
,
现在问题来了:如何存储动态选择的 key 以及在哪设置 key?
在 Servlet 的线程模型中,使用 ThreadLocal 存储 key 最合适,因此,我们编写一个 RoutingDataSourceContext,来设置并动态存储 key:
public class RoutingDataSourceContext implements AutoCloseable {
// holds data source key in thread local:
static final ThreadLocal threadLocalDataSourceKey = new ThreadLocal<>();
public static String getDataSourceRoutingKey() {
String key = threadLocalDataSourceKey.get();
return key == null ? “masterDataSource” : key;
}
public RoutingDataSourceContext(String key) {
threadLocalDataSourceKey.set(key);
}
public void close() {
threadLocalDataSourceKey.remove();
}
}
复制代码
然后,修改 RoutingDataSource,获取 key 的代码如下:
public class RoutingDataSource extends AbstractRoutingDataSource {
protected Object determineCurrentLookupKey() {
return RoutingDataSourceContext.getDataSourceRoutingKey();
}
}
复制代码
这样,在某个地方,例如一个 Controller 的方法内部,就可以动态设置 DataSource 的 Key:
@Controller
public class MyController {
@Get(“/”)
public String index() {
String key = “slaveDataSource”;
try (RoutingDataSourceContext ctx = new RoutingDataSourceContext(key)) {
// TODO:
return “html… www.liaoxuefeng.com”;
}
}
}
复制代码
到此为止,我们已经成功实现了数据库的动态路由访问。
最后
手绘了下图所示的kafka知识大纲流程图(xmind文件不能上传,导出图片展现),但都可提供源文件给每位爱学习的朋友
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
aoxuefeng.com";
}
}
}
复制代码
到此为止,我们已经成功实现了数据库的动态路由访问。
最后
手绘了下图所示的kafka知识大纲流程图(xmind文件不能上传,导出图片展现),但都可提供源文件给每位爱学习的朋友
[外链图片转存中…(img-eeCDeFoK-1714655928255)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!