增加了multi-tenant-core, multi-tenant-datasource ,未完全测试
diff --git a/multi-tenant-core/build.gradle b/multi-tenant-core/build.gradle
new file mode 100644
index 0000000..b456c6e
--- /dev/null
+++ b/multi-tenant-core/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+    id 'java'
+    id 'org.springframework.boot'
+}
+
+dependencies {
+    implementation "org.springframework:spring-webmvc"
+    implementation "javax.servlet:javax.servlet-api:${javaxServletVersion}"
+}
\ No newline at end of file
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/MultiTenantAutoConfiguration.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/MultiTenantAutoConfiguration.java
new file mode 100644
index 0000000..3ea1eb1
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/MultiTenantAutoConfiguration.java
@@ -0,0 +1,40 @@
+package com.supwisdom.multitenant;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Role;
+
+public class MultiTenantAutoConfiguration {
+
+  @Configuration
+  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
+  @ComponentScan(basePackages = {"com.supwisdom.multitenant"})
+  public static class SessionTenantInterceptorAutoConfig {
+  }
+
+  //  @ConditionalOnProperty(
+//      name = "multi-tenant.interceptor.httpsession.enabled",
+//      havingValue = "true")
+//  @Bean
+//  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
+//  @ConditionalOnBean({SessionTenantInterceptorAutoConfig.class})
+//  public SessionTenantInterceptorAutoConfig createSessionInterceptor() {
+//    return new SessionTenantInterceptorAutoConfig();
+//  }
+
+  @Configuration
+  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
+  @ComponentScan(basePackages = {"com.supwisdom.multitenant"})
+  public static class HttpHeaderTenantInterceptorAutoConfig {
+  }
+
+//  @Bean
+//  @ConditionalOnProperty(
+//      name = "multi-tenant.interceptor.httpheader.enabled",
+//      havingValue = "true")
+//  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
+//  public HttpHeaderTenantInterceptorAutoConfig createHttpHeaderInterceptor() {
+//    return new HttpHeaderTenantInterceptorAutoConfig();
+//  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantContext.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantContext.java
new file mode 100644
index 0000000..0c3bbf2
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantContext.java
@@ -0,0 +1,9 @@
+package com.supwisdom.multitenant;
+
+import java.io.Serializable;
+
+public interface TenantContext extends Serializable {
+  TenantDetails getTenant();
+
+  void setTenant(TenantDetails details);
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantContextHolder.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantContextHolder.java
new file mode 100644
index 0000000..bb0d51f
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantContextHolder.java
@@ -0,0 +1,24 @@
+package com.supwisdom.multitenant;
+
+import com.supwisdom.multitenant.impl.ThreadLocalTenantContextHolderStrategy;
+
+public class TenantContextHolder {
+  private static TenantContextHolderStrategy strategy;
+
+  static {
+    initialize();
+  }
+
+  private static void initialize() {
+    strategy = new ThreadLocalTenantContextHolderStrategy();
+  }
+
+  public static TenantContext getContext() {
+    return strategy.getContext();
+  }
+
+  public static void clearContext() {
+    strategy.clearContext();
+  }
+
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantContextHolderStrategy.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantContextHolderStrategy.java
new file mode 100644
index 0000000..300130a
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantContextHolderStrategy.java
@@ -0,0 +1,11 @@
+package com.supwisdom.multitenant;
+
+public interface TenantContextHolderStrategy {
+  TenantContext getContext();
+
+  void setContext(TenantContext tenant);
+
+  TenantContext createEmptyContext();
+
+  void clearContext();
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantDetails.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantDetails.java
new file mode 100644
index 0000000..07372bb
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantDetails.java
@@ -0,0 +1,46 @@
+package com.supwisdom.multitenant;
+
+import java.io.Serializable;
+
+public class TenantDetails implements Serializable {
+  private String id;
+
+  private String dbSchema;
+
+  private Boolean enabled;
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public String getDbSchema() {
+    return dbSchema;
+  }
+
+  public void setDbSchema(String dbSchema) {
+    this.dbSchema = dbSchema;
+  }
+
+  public Boolean getEnabled() {
+    return enabled;
+  }
+
+  public void setEnabled(Boolean enabled) {
+    this.enabled = enabled;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof TenantDetails) {
+      TenantDetails other = (TenantDetails) obj;
+      if (getId().equals(other.getId())) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantInterceptor.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantInterceptor.java
new file mode 100644
index 0000000..3a50249
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantInterceptor.java
@@ -0,0 +1,7 @@
+package com.supwisdom.multitenant;
+
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+public abstract class TenantInterceptor extends HandlerInterceptorAdapter {
+
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableHttpHeaderTenantInterceptor.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableHttpHeaderTenantInterceptor.java
new file mode 100644
index 0000000..97f8625
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableHttpHeaderTenantInterceptor.java
@@ -0,0 +1,13 @@
+package com.supwisdom.multitenant.annotations;
+
+import com.supwisdom.multitenant.MultiTenantAutoConfiguration;
+import org.springframework.context.annotation.Import;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Import(MultiTenantAutoConfiguration.HttpHeaderTenantInterceptorAutoConfig.class)
+@Documented
+public @interface EnableHttpHeaderTenantInterceptor {
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableSessionTenantInterceptor.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableSessionTenantInterceptor.java
new file mode 100644
index 0000000..885140b
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableSessionTenantInterceptor.java
@@ -0,0 +1,13 @@
+package com.supwisdom.multitenant.annotations;
+
+import com.supwisdom.multitenant.MultiTenantAutoConfiguration;
+import org.springframework.context.annotation.Import;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Import(MultiTenantAutoConfiguration.SessionTenantInterceptorAutoConfig.class)
+@Documented
+public @interface EnableSessionTenantInterceptor {
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/HttpHeaderWebMvcConfig.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/HttpHeaderWebMvcConfig.java
new file mode 100644
index 0000000..b2d9585
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/HttpHeaderWebMvcConfig.java
@@ -0,0 +1,23 @@
+package com.supwisdom.multitenant.config;
+
+
+import com.supwisdom.multitenant.impl.HttpHeaderTenantInterceptor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+@ConditionalOnBean(value = {HttpHeaderTenantInterceptor.class})
+public class HttpHeaderWebMvcConfig implements WebMvcConfigurer {
+  private final HttpHeaderTenantInterceptor interceptor;
+
+  public HttpHeaderWebMvcConfig(HttpHeaderTenantInterceptor interceptor) {
+    this.interceptor = interceptor;
+  }
+
+  @Override
+  public void addInterceptors(InterceptorRegistry registry) {
+    registry.addInterceptor(interceptor);
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/TenantCoreUtils.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/TenantCoreUtils.java
new file mode 100644
index 0000000..97c7096
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/TenantCoreUtils.java
@@ -0,0 +1,6 @@
+package com.supwisdom.multitenant.config;
+
+public final class TenantCoreUtils {
+  public static final String INTERNAL_TENANT_INTERCEPTOR_BEAN_NAME = "coms.supwisdom.multitenant.interceptor";
+
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/TenantHeaderProperties.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/TenantHeaderProperties.java
new file mode 100644
index 0000000..4d31390
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/TenantHeaderProperties.java
@@ -0,0 +1,20 @@
+package com.supwisdom.multitenant.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties("multi-tenant.header")
+public class TenantHeaderProperties {
+  @Value("${key:X-Tenant-Id}")
+  private String key;
+
+  public String getKey() {
+    return key;
+  }
+
+  public void setKey(String key) {
+    this.key = key;
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/TenantJwtProperties.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/TenantJwtProperties.java
new file mode 100644
index 0000000..c4dcbb4
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/TenantJwtProperties.java
@@ -0,0 +1,31 @@
+package com.supwisdom.multitenant.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties("multi-tenant.jwt")
+public class TenantJwtProperties {
+  @Value("${header:Authentication}")
+  private String jwtHeader;
+
+  @Value("${schema:Bears}")
+  private String schema;
+
+  public String getJwtHeader() {
+    return jwtHeader;
+  }
+
+  public void setJwtHeader(String jwtHeader) {
+    this.jwtHeader = jwtHeader;
+  }
+
+  public String getSchema() {
+    return schema;
+  }
+
+  public void setSchema(String schema) {
+    this.schema = schema;
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/TenantSessionProperties.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/TenantSessionProperties.java
new file mode 100644
index 0000000..3d57c62
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/TenantSessionProperties.java
@@ -0,0 +1,20 @@
+package com.supwisdom.multitenant.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties("multi-tenant.session")
+public class TenantSessionProperties {
+  @Value("${name:multi-tenant-id}")
+  private String name;
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/HttpHeaderTenantInterceptor.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/HttpHeaderTenantInterceptor.java
new file mode 100644
index 0000000..b8ae342
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/HttpHeaderTenantInterceptor.java
@@ -0,0 +1,47 @@
+package com.supwisdom.multitenant.impl;
+
+import com.supwisdom.multitenant.*;
+import com.supwisdom.multitenant.config.TenantHeaderProperties;
+import com.supwisdom.multitenant.config.TenantJwtProperties;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Component
+@ConditionalOnBean(MultiTenantAutoConfiguration.HttpHeaderTenantInterceptorAutoConfig.class)
+public class HttpHeaderTenantInterceptor extends TenantInterceptor {
+  private final TenantJwtProperties properties;
+
+  private final TenantHeaderProperties headerProperties;
+
+  public HttpHeaderTenantInterceptor(TenantJwtProperties properties,
+                                     TenantHeaderProperties headerProperties) {
+    this.properties = properties;
+    this.headerProperties = headerProperties;
+  }
+
+  @Override
+  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+    String tenant = request.getHeader(headerProperties.getKey());
+    if (tenant != null && !StringUtils.isEmpty(tenant)) {
+      TenantDetails details = new TenantDetails();
+      details.setId(tenant);
+      TenantContextHolder.getContext().setTenant(details);
+    }
+    String header = request.getHeader(properties.getJwtHeader());
+    if (header.startsWith(properties.getSchema())) {
+      // parse jwt
+    }
+    return super.preHandle(request, response, handler);
+  }
+
+  @Override
+  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
+                         ModelAndView modelAndView) throws Exception {
+    TenantContextHolder.clearContext();
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/SessionTenantInterceptor.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/SessionTenantInterceptor.java
new file mode 100644
index 0000000..3f9ae2c
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/SessionTenantInterceptor.java
@@ -0,0 +1,39 @@
+package com.supwisdom.multitenant.impl;
+
+import com.supwisdom.multitenant.*;
+import com.supwisdom.multitenant.config.TenantSessionProperties;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Component
+@ConditionalOnBean(MultiTenantAutoConfiguration.SessionTenantInterceptorAutoConfig.class)
+public class SessionTenantInterceptor extends TenantInterceptor {
+  private final TenantSessionProperties properties;
+
+  public SessionTenantInterceptor(TenantSessionProperties properties) {
+    this.properties = properties;
+  }
+
+  @Override
+  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+    String tenant = (String) request.getSession().getAttribute(properties.getName());
+    if (tenant != null && !StringUtils.isEmpty(tenant)) {
+      TenantDetails details = new TenantDetails();
+      details.setId(tenant);
+      TenantContextHolder.getContext().setTenant(details);
+    }
+    return super.preHandle(request, response, handler);
+  }
+
+  @Override
+  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
+                         ModelAndView modelAndView) throws Exception {
+    TenantContextHolder.clearContext();
+    super.postHandle(request, response, handler, modelAndView);
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/TenantContextImpl.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/TenantContextImpl.java
new file mode 100644
index 0000000..39bdae8
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/TenantContextImpl.java
@@ -0,0 +1,27 @@
+package com.supwisdom.multitenant.impl;
+
+import com.supwisdom.multitenant.TenantContext;
+import com.supwisdom.multitenant.TenantDetails;
+
+public class TenantContextImpl implements TenantContext {
+  private TenantDetails details;
+
+  @Override
+  public TenantDetails getTenant() {
+    return details;
+  }
+
+  @Override
+  public void setTenant(TenantDetails details) {
+    this.details = details;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof TenantContextImpl) {
+      TenantContextImpl other = (TenantContextImpl) obj;
+      getTenant().equals(other.getTenant());
+    }
+    return false;
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/ThreadLocalTenantContextHolderStrategy.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/ThreadLocalTenantContextHolderStrategy.java
new file mode 100644
index 0000000..fd325ec
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/ThreadLocalTenantContextHolderStrategy.java
@@ -0,0 +1,33 @@
+package com.supwisdom.multitenant.impl;
+
+import com.supwisdom.multitenant.TenantContext;
+import com.supwisdom.multitenant.TenantContextHolderStrategy;
+
+public class ThreadLocalTenantContextHolderStrategy implements TenantContextHolderStrategy {
+  private static final ThreadLocal<TenantContext> contextHolder = new ThreadLocal<>();
+
+  @Override
+  public TenantContext getContext() {
+    TenantContext context = contextHolder.get();
+    if (context == null) {
+      context = createEmptyContext();
+      contextHolder.set(context);
+    }
+    return context;
+  }
+
+  @Override
+  public void setContext(TenantContext tenant) {
+    contextHolder.set(tenant);
+  }
+
+  @Override
+  public void clearContext() {
+    contextHolder.remove();
+  }
+
+  @Override
+  public TenantContext createEmptyContext() {
+    return new TenantContextImpl();
+  }
+}
diff --git a/multi-tenant-core/src/test/java/com/supwisdom/multitenant/AutoConfigurationTest.java b/multi-tenant-core/src/test/java/com/supwisdom/multitenant/AutoConfigurationTest.java
new file mode 100644
index 0000000..4286f3c
--- /dev/null
+++ b/multi-tenant-core/src/test/java/com/supwisdom/multitenant/AutoConfigurationTest.java
@@ -0,0 +1,33 @@
+package com.supwisdom.multitenant;
+
+import com.supwisdom.multitenant.annotations.EnableSessionTenantInterceptor;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.Arrays;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+
+@SpringBootTest(classes = {AutoConfigurationTest.class})
+@EnableSessionTenantInterceptor
+@TestPropertySource("/test.properties")
+public class AutoConfigurationTest {
+
+  @Autowired
+  private ApplicationContext appContext;
+
+  @Test
+  public void testSessionOk() {
+    String[] beans = appContext.getBeanDefinitionNames();
+    Arrays.sort(beans);
+    for (String bean : beans) {
+      System.out.println(bean);
+    }
+    assertThat(TenantContextHolder.getContext(), notNullValue());
+  }
+
+}
diff --git a/multi-tenant-core/src/test/resources/test.properties b/multi-tenant-core/src/test/resources/test.properties
new file mode 100644
index 0000000..80c6377
--- /dev/null
+++ b/multi-tenant-core/src/test/resources/test.properties
@@ -0,0 +1 @@
+debug=true
\ No newline at end of file