[英]How to connect to multiple MySQL databases as per the header in REST API request
我正在创建一个多租户Spring Boot-JPA应用程序。
在此应用程序中,我想使用通过API请求作为标头发送的数据库名称连接到MySQL数据库。
我在线检查了许多多租户项目示例,但仍然找不到解决方案。
有人可以建议我这样做吗?
您可以使用AbstractRoutingDataSource
来实现。 AbstractRoutingDataSource
需要一些信息来知道要路由到哪个实际DataSource
(称为Context ),该信息由determineCurrentLookupKey()
方法提供。 从这里使用示例。
定义上下文,例如:
public enum ClientDatabase {
CLIENT_A, CLIENT_B
}
然后,您需要定义Context Holder,该上下文将在determineCurrentLookupKey()
public class ClientDatabaseContextHolder {
private static ThreadLocal<ClientDatabase> CONTEXT = new ThreadLocal<>();
public static void set(ClientDatabase clientDatabase) {
Assert.notNull(clientDatabase, "clientDatabase cannot be null");
CONTEXT.set(clientDatabase);
}
public static ClientDatabase getClientDatabase() {
return CONTEXT.get();
}
public static void clear() {
CONTEXT.remove();
}
}
然后,您可以扩展AbstractRoutingDataSource
如下所示:
public class ClientDataSourceRouter extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return ClientDatabaseContextHolder.getClientDatabase();
}
}
最后, DataSource
bean配置:
@Bean
public DataSource clientDatasource() {
Map<Object, Object> targetDataSources = new HashMap<>();
DataSource clientADatasource = clientADatasource();
DataSource clientBDatasource = clientBDatasource();
targetDataSources.put(ClientDatabase.CLIENT_A,
clientADatasource);
targetDataSources.put(ClientDatabase.CLIENT_B,
clientBDatasource);
ClientDataSourceRouter clientRoutingDatasource
= new ClientDataSourceRouter();
clientRoutingDatasource.setTargetDataSources(targetDataSources);
clientRoutingDatasource.setDefaultTargetDataSource(clientADatasource);
return clientRoutingDatasource;
}
https://github.com/wmeints/spring-multi-tenant-demo
按照这个逻辑,我现在可以解决它。 一些版本需要升级,代码也需要升级。
Spring Boot版本已更改。
org.springframework.boot spring-boot-starter-parent 2.1.0.RELEASE
Mysql版本已被删除。
在MultitenantConfiguration.java
一些小的更改
@Configuration public class MultitenantConfiguration { @Autowired private DataSourceProperties properties; /** * Defines the data source for the application * @return */ @Bean @ConfigurationProperties( prefix = "spring.datasource" ) public DataSource dataSource() { File[] files = Paths.get("tenants").toFile().listFiles(); Map<Object,Object> resolvedDataSources = new HashMap<>(); if(files != null) { for (File propertyFile : files) { Properties tenantProperties = new Properties(); DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(this.getClass().getClassLoader()); try { tenantProperties.load(new FileInputStream(propertyFile)); String tenantId = tenantProperties.getProperty("name"); dataSourceBuilder.driverClassName(properties.getDriverClassName()) .url(tenantProperties.getProperty("datasource.url")) .username(tenantProperties.getProperty("datasource.username")) .password(tenantProperties.getProperty("datasource.password")); if (properties.getType() != null) { dataSourceBuilder.type(properties.getType()); } resolvedDataSources.put(tenantId, dataSourceBuilder.build()); } catch (IOException e) { e.printStackTrace(); return null; } } } // Create the final multi-tenant source. // It needs a default database to connect to. // Make sure that the default database is actually an empty tenant database. // Don't use that for a regular tenant if you want things to be safe! MultitenantDataSource dataSource = new MultitenantDataSource(); dataSource.setDefaultTargetDataSource(defaultDataSource()); dataSource.setTargetDataSources(resolvedDataSources); // Call this to finalize the initialization of the data source. dataSource.afterPropertiesSet(); return dataSource; } /** * Creates the default data source for the application * @return */ private DataSource defaultDataSource() { DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(this.getClass().getClassLoader()) .driverClassName(properties.getDriverClassName()) .url(properties.getUrl()) .username(properties.getUsername()) .password(properties.getPassword()); if(properties.getType() != null) { dataSourceBuilder.type(properties.getType()); } return dataSourceBuilder.build(); }
}
发生此更改是由于DataSourceBuilder
已移至另一个路径,并且其构造函数已更改。
还像这样在application.properties
更改了MySQL驱动程序类名称
spring.datasource.driver类名= com.mysql.jdbc.Driver
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.