Spring Data MongoDB惰性配置数据库连接

时间:2018-10-26 13:08:10

标签: java spring mongodb multi-tenant spring-data-mongodb

我有一个多租户的mongoDB应用程序,让我们假设 从HTTP请求标头中的租户名称中选择到正确数据库的正确连接(i使用较早准备的带有租户名称的属性文件)。 当应用程序启动时,mongoDB正在配置,并且我没有有关租户的信息,因为尚未发送对应用程序的任何请求,因此我不知道我应该连接到哪个数据库。当我尝试从mongo存储库中获取一些数据(然后我从HTTP请求获得租户名称)时,是否有可能动态配置mongoDB与数据库的连接?

MongoDbConfiguration:

@Configuration
public class MongoDbConfiguration {

    private final MongoConnector mongoConnector;

    @Autowired
    public MongoDbConfiguration(MongoConnector mongoConnector) {
        this.mongoConnector = mongoConnector;
    }

    @Bean
    public MongoDbFactory mongoDbFactory() {
        return new MultiTenantSingleMongoDbFactory(mongoConnector, new MongoExceptionTranslator());
    }

    @Bean
    public MongoTemplate mongoTemplate() {
        return new MongoTemplate(mongoDbFactory());
    }
}

1 个答案:

答案 0 :(得分:1)

@Component
@Slf4j
public class MultiTenantMongoDbFactory extends SimpleMongoDbFactory {

  private static final Logger logger = LoggerFactory.getLogger(MultiTenantMongoDbFactory.class);

  private Map<String, DbConfig> tenantToDbConfig;

  private Map<String, MongoDatabase> tenantToMongoDatabase;

  @Autowired
  public MultiTenantMongoDbFactory(
      final @Qualifier("sibTenantContexts") Map<String, DbConfig> dbConfigs,
      final SibEnvironment env) {

    super(new MongoClientURI(env.getDefaultDatabase()));
    this.tenantToDbConfig = dbConfigs;
    // Initialize tenantToMongoDatabase map.
    buildTenantDbs();
  }

  @Override
  public MongoDatabase getDb() {

    String tenantId = (!StringUtils.isEmpty(TenantContext.getId()) ? TenantContext.getId()
        : SibConstant.DEFAULT_TENANT);
    return this.tenantToMongoDatabase.get(tenantId);
  }

  /**
   * Create tenantToMongoDatabase map.
   */
  @SuppressWarnings("resource")
  private void buildTenantDbs() {

    log.debug("Building tenantDB configuration.");
    this.tenantToMongoDatabase = new HashMap<>();
    /*
     * for each tenant fetch dbConfig and intitialize MongoClient and set it to
     * tenantToMongoDatabase
     */
    for (Entry<String, DbConfig> idToDbconfig : this.tenantToDbConfig.entrySet()) {
      try {
        this.tenantToMongoDatabase.put(idToDbconfig.getKey(),
            new MongoClient(new MongoClientURI(idToDbconfig.getValue()
                .getUri())).getDatabase(idToDbconfig.getValue()
                    .getDatabase()));
      } catch (MongoException e) {
        log.error(e.getMessage(), e.getCause());
      }
    }
  }
}

在此,tenantToDbConfig是我在应用程序启动时创建的一个Bean,我在其中将DBConfiguration((URL /数据库名称))存储在每个租户中。引导时需要一个默认数据库,对于每个请求,我都希望在请求标头中有tenantId。