繁体   English   中英

如何根据REST API请求中的标头连接到多个MySQL数据库

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM