嗨专家,
我正在开展多租户项目。这是每个租户架构的表格 为此,我们正在使用spring和JPA(eclipse-link)。 在这里,我们的用例是,当新客户订阅我们的应用程序时,将为客户创建新的数据库。
由于Spring配置只在启动时加载,如何在运行时加载这个新的db配置?
有人可以给点指点吗? 提前谢谢。
BR, 小猫
答案 0 :(得分:0)
对于multitenan,首先需要创建MultitenantConfig.java
喜欢下面的文件。
这里tenants.get("Musa")
是我的租户名称,来自application.properties文件
@Configuration
@EnableConfigurationProperties(MultitenantProperties.class)
public class MultiTenantConfig extends WebMvcConfigurerAdapter {
/** The Constant log. */
private static final Logger log = LoggerFactory.getLogger(MultiTenantConfig.class);
/** The multitenant config. */
@Autowired
private MultitenantProperties multitenantConfig;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MultiTenancyInterceptor());
}
/**
* Data source.
*
* @return the data source
*/
@Bean
public DataSource dataSource() {
Map<Object, Object> tenants = getTenants();
MultitenantDataSource multitenantDataSource = new MultitenantDataSource();
multitenantDataSource.setDefaultTargetDataSource(tenants.get("Musa"));
multitenantDataSource.setTargetDataSources(tenants);
// Call this to finalize the initialization of the data source.
multitenantDataSource.afterPropertiesSet();
return multitenantDataSource;
}
/**
* Gets the tenants.
*
* @return the tenants
*/
private Map<Object, Object> getTenants() {
Map<Object, Object> resolvedDataSources = new HashMap<>();
for (Tenant tenant : multitenantConfig.getTenants()) {
DataSourceBuilder dataSourceBuilder = new DataSourceBuilder(this.getClass().getClassLoader());
dataSourceBuilder.driverClassName(tenant.getDriverClassName()).url(tenant.getUrl())
.username(tenant.getUsername()).password(tenant.getPassword());
DataSource datasource = dataSourceBuilder.build();
for (String prop : tenant.getTomcat().keySet()) {
try {
BeanUtils.setProperty(datasource, prop, tenant.getTomcat().get(prop));
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("Could not set property " + prop + " on datasource " + datasource);
}
}
log.info(datasource.toString());
resolvedDataSources.put(tenant.getName(), datasource);
}
return resolvedDataSources;
}
}
public class MultitenantDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return TenantContext.getCurrentTenant();
}
}
public class MultiTenancyInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
TenantContext.setCurrentTenant("Musa");
return true;
}
}
@ConfigurationProperties(prefix = "multitenancy")
public class MultitenantProperties {
public static final String CURRENT_TENANT_IDENTIFIER = "tenantId";
public static final int CURRENT_TENANT_SCOPE = 0;
private List<Tenant> tenants;
public List<Tenant> getTenants() {
return tenants;
}
public void setTenants(List<Tenant> tenants) {
this.tenants = tenants;
}
}
public class Tenant {
private String name;
private String url;
private String driverClassName;
private String username;
private String password;
private Map<String,String> tomcat;
//setter gettter
public class TenantContext {
private static ThreadLocal<Object> currentTenant = new ThreadLocal<>();
public static void setCurrentTenant(Object tenant) {
currentTenant.set(tenant);
}
public static Object getCurrentTenant() {
return currentTenant.get();
}
}
在application.properties
中添加以下属性multitenancy.tenants[0].name=Musa
multitenancy.tenants[0].url<url>
multitenancy.tenants[0].username=<username>
multitenancy.tenants[0].password=<password>
multitenancy.tenants[0].driver-class-name=<driverclass>