如何根据restapi请求中的头连接到多个mysql数据库

23c0lvtd  于 2021-06-15  发布在  Mysql
关注(0)|答案(2)|浏览(261)

我正在创建一个多租户spring boot-jpa应用程序。
在这个应用程序中,我想使用db name连接mysql数据库,db name是通过api请求作为头发送的。
我在网上查看了许多多租户项目示例,但仍然找不到解决方案。
有人能给我建议一个方法吗?

55ooxyrt

55ooxyrt1#

你可以用 AbstractRoutingDataSource 为了达到这个目的。 AbstractRoutingDataSource 需要信息来知道 DataSource 路由到(称为上下文),由 determineCurrentLookupKey() 方法。用这里的例子。
定义上下文如下:

public enum ClientDatabase {
    CLIENT_A, CLIENT_B
}

然后您需要定义将在中使用的上下文持有者 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;

}

falq053o

falq053o2#

https://github.com/wmeints/spring-multi-tenant-demo
按照这个逻辑,我现在可以解决了。有些版本需要升级,代码也需要升级。
Spring 启动版本已更改。
org.springframework.boot spring boot starter父版本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` 已移动到另一个路径,并且其构造函数已更改。
还更改了中的mysql驱动程序类名 `application.properties` 这样地
spring.datasource.driver类名=com.mysql.jdbc.driver

相关问题