春天的多租户应用程序 - 连接到数据库

时间:2017-12-05 10:14:40

标签: spring-data-jpa multi-tenant

嗨专家,

我正在开展多租户项目。这是每个租户架构的表格 为此,我们正在使用spring和JPA(eclipse-link)。 在这里,我们的用例是,当新客户订阅我们的应用程序时,将为客户创建新的数据库。

由于Spring配置只在启动时加载,如何在运行时加载这个新的db配置?

有人可以给点指点吗? 提前谢谢。

BR, 小猫

1 个答案:

答案 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>