2017-12-05 34 views
1

안녕 전문가에 연결멀티 테넌트 (multi-tenant) 응용 프로그램 - DB

나는 멀티 테넌트 (multi-tenant) 프로젝트를 진행하고있다. 이것은 테넌트 아키텍처 당 테이블입니다.
우리는이 목적으로 spring과 JPA (eclipse-link)를 사용하고 있습니다. 우리의 유스 케이스는 새로운 고객이 우리 애플리케이션에 가입 할 때 고객을 위해 새로운 데이터베이스가 생성 될 때입니다.

스프링 구성은 시작 중에 만로드되므로이 새로운 db 구성을 런타임에로드하는 방법은 무엇입니까?

일부 포인터를 알려주시겠습니까? 미리 감사드립니다.

BR, 키티 multitenan를 들어

답변

0

먼저 당신이 파일을 아래와 같이 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(); 
    } 
} 

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> 
+0

새로운 DB를 생성 할 것이다 application.properties에 속성 아래 추가 파일에서 오는 때마다 새로운 고객 등록을 . – user3305063

+0

내 이전 의견을 무시하십시오. 새 고객은 우리 고객의 애플 리케이션에 등록 할 때마다 만들어 질 것입니다. 따라서 컴파일 시간 동안 application.properties에서 구성 할 DB 수를 알 수 없습니다. 내가 생각하고 있던 것은 고객이 등록 할 때마다 URL과 이름과 같은 DB 정보와 세입자 ID가 들어있는 마스터 디렉토리 (테이블)를 만드는 것입니다. 그러나 문제는 동일한 데이터 소스를 만드는 방법입니다. 이 방법을 알려 주시기 바랍니다. 만약 당신이 생각하는 경우 다른 좋은 방법을 알려주십시오 알려주십시오. – user3305063

+0

MultitenantProperties이 개체에서 런타임 속성을 구성 할 수 있습니다. – Musaddique