移植多租户,未完全实现
diff --git a/build.gradle b/build.gradle
index 96a615d..7a92f84 100644
--- a/build.gradle
+++ b/build.gradle
@@ -37,7 +37,6 @@
     implementation 'org.springframework.social:spring-social-web:1.1.6.RELEASE'
     implementation 'org.jetbrains.kotlin:kotlin-reflect'
     implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
-    implementation 'org.hibernate:hibernate-validator:5.4.1.Final'
 
     implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
 
diff --git a/config/application-devel-pg.properties b/config/application-devel-pg.properties
index fbe89a4..fa16807 100644
--- a/config/application-devel-pg.properties
+++ b/config/application-devel-pg.properties
@@ -31,12 +31,4 @@
 #spring.jpa.properties.hibernate.multiTenancy=DATABASE
 #spring.jpa.properties.hibernate.tenant_identifier_resolver=com.supwisdom.dlpay.framework.tenant.MultiTenantIdentifierResolver
 #spring.jpa.properties.hibernate.multi_tenant_connection_provider=com.supwisdom.dlpay.framework.tenant.MultiTenantConnectionProviderImpl
-datasource.driverClass=org.postgresql.Driver
-datasource.url=jdbc:postgresql://172.28.201.70:15432/payapi
-datasource.username=payapi
-datasource.password=123456
-datasource.maxActive=100
-datasource.maxIdle=30
-datasource.maxWait=30
-datasource.minIdle=5
 ##################多租户配置 end################################
\ No newline at end of file
diff --git a/src/main/java/com/supwisdom/dlpay/AppPreparedEvent.java b/src/main/java/com/supwisdom/dlpay/AppPreparedEvent.java
index 304379c..4dead6a 100644
--- a/src/main/java/com/supwisdom/dlpay/AppPreparedEvent.java
+++ b/src/main/java/com/supwisdom/dlpay/AppPreparedEvent.java
@@ -6,7 +6,7 @@
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.event.EventListener;
 
-@Configuration
+//@Configuration
 public class AppPreparedEvent {
   private final DictPool dictPool;
 
diff --git a/src/main/java/com/supwisdom/dlpay/framework/tenant/HibernateConfig.java b/src/main/java/com/supwisdom/dlpay/framework/tenant/HibernateConfig.java
new file mode 100644
index 0000000..947e0ab
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/tenant/HibernateConfig.java
@@ -0,0 +1,63 @@
+package com.supwisdom.dlpay.framework.tenant;
+
+import org.hibernate.MultiTenancyStrategy;
+import org.hibernate.cfg.Environment;
+import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
+import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
+import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.orm.jpa.JpaVendorAdapter;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
+
+import javax.persistence.EntityManagerFactory;
+import javax.sql.DataSource;
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+public class HibernateConfig {
+  private final JpaProperties jpaProperties;
+
+  private final HibernateProperties hibernateProperties;
+
+  public HibernateConfig(@Autowired JpaProperties jpaProperties,
+                         HibernateProperties hibernateProperties) {
+    this.jpaProperties = jpaProperties;
+    this.hibernateProperties = hibernateProperties;
+  }
+
+  @Bean
+  public JpaVendorAdapter getJpaVendorAdapter() {
+    return new HibernateJpaVendorAdapter();
+  }
+
+  @Bean
+  public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource dataSource,
+                                                                         MultiTenantConnectionProvider multiTenantConnectionProvider,
+                                                                         CurrentTenantIdentifierResolver currentTenantIdentifierResolver) {
+    Map<String, Object> properties = new HashMap<>();
+    properties.putAll(hibernateProperties
+        .determineHibernateProperties(jpaProperties.getProperties(),
+            new HibernateSettings()));
+    properties.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
+    properties.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider);
+    properties.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolver);
+
+    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
+    em.setDataSource(dataSource);
+    em.setPackagesToScan("com.supwisdom");
+    em.setJpaPropertyMap(properties);
+    em.setJpaVendorAdapter(getJpaVendorAdapter());
+    return em;
+  }
+
+  @Bean
+  public EntityManagerFactory entityManagerFactoryBean(LocalContainerEntityManagerFactoryBean localBean) {
+    return localBean.getNativeEntityManagerFactory();
+  }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/tenant/MultiTenantConnectionProviderImpl.java b/src/main/java/com/supwisdom/dlpay/framework/tenant/MultiTenantConnectionProviderImpl.java
index 0f1d799..7a0fb8a 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/tenant/MultiTenantConnectionProviderImpl.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/tenant/MultiTenantConnectionProviderImpl.java
@@ -1,20 +1,67 @@
 package com.supwisdom.dlpay.framework.tenant;
 
+import org.hibernate.HibernateException;
 import org.hibernate.engine.jdbc.connections.spi.AbstractDataSourceBasedMultiTenantConnectionProviderImpl;
+import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
 
 import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
 
 /**
  * Created by shuwei on 2018/12/4.
  */
-public class MultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl {
-    @Override
-    protected DataSource selectAnyDataSource() {
-        return TenantDataSourceProvider.getTenantDataSource("default");
-    }
+@Component
+public class MultiTenantConnectionProviderImpl implements MultiTenantConnectionProvider {
+  @Autowired
+  private DataSource dataSource;
 
-    @Override
-    protected DataSource selectDataSource(String tenantIdentifier) {
-        return TenantDataSourceProvider.getTenantDataSource(TenantThread.getTenantSchema());
+  @Override
+  public Connection getAnyConnection() throws SQLException {
+    return dataSource.getConnection();
+  }
+
+  @Override
+  public void releaseAnyConnection(Connection connection) throws SQLException {
+    connection.close();
+  }
+
+  @Override
+  public Connection getConnection(String ti) throws SQLException {
+    String tenantIdentifier = TenantContext.getTenantSchema();
+    final Connection connection = getAnyConnection();
+    try {
+      if (tenantIdentifier != null) {
+        connection.createStatement().execute("SET search_path = " + tenantIdentifier + ", public");
+      } else {
+        connection.createStatement().execute("SET search_path =  public");
+      }
+    } catch (SQLException e) {
+      throw new HibernateException("Problem setting schema to " + tenantIdentifier, e);
     }
+    return connection;
+  }
+
+  @Override
+  public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
+    connection.close();
+  }
+
+  @Override
+  public boolean supportsAggressiveRelease() {
+    return false;
+  }
+
+  @SuppressWarnings("rawtypes")
+  @Override
+  public boolean isUnwrappableAs(Class unwrapType) {
+    return false;
+  }
+
+  @Override
+  public <T> T unwrap(Class<T> unwrapType) {
+    return null;
+  }
 }
diff --git a/src/main/java/com/supwisdom/dlpay/framework/tenant/MultiTenantIdentifierResolver.java b/src/main/java/com/supwisdom/dlpay/framework/tenant/MultiTenantIdentifierResolver.java
index d2dc781..c1dc432 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/tenant/MultiTenantIdentifierResolver.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/tenant/MultiTenantIdentifierResolver.java
@@ -1,21 +1,23 @@
 package com.supwisdom.dlpay.framework.tenant;
 
 import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
+import org.springframework.stereotype.Component;
 
 /**
  * Created by shuwei on 2018/12/4.
  */
+@Component
 public class MultiTenantIdentifierResolver implements CurrentTenantIdentifierResolver {
-    @Override
-    public String resolveCurrentTenantIdentifier() {
-        if(TenantThread.getTenantSchema()==null){
-            return "default";
-        }
-        return TenantThread.getTenantSchema();
+  @Override
+  public String resolveCurrentTenantIdentifier() {
+    if (TenantContext.getTenantSchema() == null) {
+      return "default";
     }
+    return TenantContext.getTenantSchema();
+  }
 
-    @Override
-    public boolean validateExistingCurrentSessions() {
-        return true;
-    }
+  @Override
+  public boolean validateExistingCurrentSessions() {
+    return true;
+  }
 }
diff --git a/src/main/java/com/supwisdom/dlpay/framework/tenant/TenantContext.java b/src/main/java/com/supwisdom/dlpay/framework/tenant/TenantContext.java
new file mode 100644
index 0000000..bbee36a
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/tenant/TenantContext.java
@@ -0,0 +1,16 @@
+package com.supwisdom.dlpay.framework.tenant;
+
+/**
+ * Created by shuwei on 2018/11/29.
+ */
+public class TenantContext {
+    private static ThreadLocal<String> currentTenant = new ThreadLocal<>();
+
+    public static void setTenantSchema(String tid) {
+        currentTenant.set(tid);
+    }
+
+    public static String getTenantSchema() {
+        return currentTenant.get();
+    }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/tenant/TenantDataSourceProvider.java b/src/main/java/com/supwisdom/dlpay/framework/tenant/TenantDataSourceProvider.java
deleted file mode 100644
index d93db46..0000000
--- a/src/main/java/com/supwisdom/dlpay/framework/tenant/TenantDataSourceProvider.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.supwisdom.dlpay.framework.tenant;
-
-import org.apache.commons.dbcp.BasicDataSource;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.PostConstruct;
-import javax.sql.DataSource;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Created by shuwei on 2018/12/4.
- */
-@Component
-public class TenantDataSourceProvider {
-    @Value("${datasource.driverClass}")
-    private String driver;
-    @Value("${datasource.url}")
-    private String url;
-    @Value("${datasource.username}")
-    private String username;
-    @Value("${datasource.password}")
-    private String password;
-    @Value("${datasource.maxIdle}")
-    private int maxIdle;
-    @Value("${datasource.maxActive}")
-    private int maxActive;
-    @Value("${datasource.minIdle}")
-    private int minIdle;
-    @Value("${datasource.maxWait}")
-    private int maxWait;
-
-    public static String static_driver;
-    public static String static_url;
-    public static String static_username;
-    public static String static_password;
-    public static int static_maxIdle;
-    public static int static_maxActive;
-    public static int static_minIdle;
-    public static int static_maxWait;
-
-
-    @PostConstruct
-    public void beforeInit() {
-        static_driver = driver;
-        static_url = url;
-        static_username = username;
-        static_password = password;
-        static_maxIdle = maxIdle;
-        static_maxActive = maxActive;
-        static_minIdle = minIdle;
-        static_maxWait = maxWait;
-    }
-    // 使用一个map来存储我们租户和对应的数据源,租户和数据源的信息就是从我们的tenant_info表中读出来
-    private static Map<String, DataSource> dataSourceMap = new HashMap<>();
-
-    /**
-     * 静态建立一个数据源,也就是我们的默认数据源,假如我们的访问信息里面没有指定tenantId,就使用默认数据源。
-     * 在我这里默认数据源是cloud_config,实际上你可以指向你们的公共信息的库,或者拦截这个操作返回错误。
-     */
-    // 根据传进来的tenantId决定返回的数据源
-    public static DataSource getTenantDataSource(String schemaId) {
-        DataSource d = dataSourceMap.get(schemaId);
-        if (d == null) {
-            String appSchema = schemaId != null ? "'" + schemaId + "','public'" : "'public'";
-            String searchPath = "SET search_path = " + appSchema + ";";
-            d = createDataSource(schemaId == null, searchPath);
-            dataSourceMap.put(schemaId, d);
-        }
-        return d;
-    }
-
-    // 初始化的时候用于添加数据源的方法
-    public static DataSource createDataSource(boolean rootdatabase, String searchPath) {
-        BasicDataSource dataSource = new BasicDataSource();
-        dataSource.setDriverClassName(static_driver);
-        dataSource.setUrl(static_url);
-        dataSource.setUsername(static_username);
-        dataSource.setPassword(static_password);
-        dataSource.setMaxActive(static_maxActive);
-        dataSource.setMaxIdle(static_maxIdle);
-        dataSource.setMaxWait(static_maxWait);
-        dataSource.setMinIdle(static_minIdle);
-        if(static_driver.toLowerCase().contains("oracle")){
-            dataSource.setValidationQuery("select 1 from dual");
-        }else {
-            dataSource.setValidationQuery("select 1 ");
-            if(static_driver.toLowerCase().contains("postgresql")) {
-                dataSource.setConnectionInitSqls(Collections.singletonList(searchPath));
-            }
-        }
-        return dataSource;
-    }
-}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/tenant/TenantInterceptor.java b/src/main/java/com/supwisdom/dlpay/framework/tenant/TenantInterceptor.java
new file mode 100644
index 0000000..73bdbea
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/tenant/TenantInterceptor.java
@@ -0,0 +1,28 @@
+package com.supwisdom.dlpay.framework.tenant;
+
+import com.supwisdom.dlpay.framework.util.Constants;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Component
+public class TenantInterceptor extends HandlerInterceptorAdapter {
+
+  @Override
+  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+      throws Exception {
+    String tenantId = request.getHeader(Constants.HEADER_TETANTID);
+    TenantContext.setTenantSchema(tenantId);
+    return true;
+  }
+
+  @Override
+  public void postHandle(HttpServletRequest request, HttpServletResponse response,
+                         Object handler, ModelAndView modelAndView)
+      throws Exception {
+    //
+  }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/tenant/TenantThread.java b/src/main/java/com/supwisdom/dlpay/framework/tenant/TenantThread.java
deleted file mode 100644
index 2bfb113..0000000
--- a/src/main/java/com/supwisdom/dlpay/framework/tenant/TenantThread.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.supwisdom.dlpay.framework.tenant;
-
-/**
- * Created by shuwei on 2018/11/29.
- */
-public class TenantThread {
-    private static ThreadLocal<String> tenant_schema = new ThreadLocal<>();
-
-    public static void setTenantSchema(String tid) {
-        tenant_schema.set(tid);
-    }
-
-    public static String getTenantSchema() {
-        return tenant_schema.get();
-    }
-}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/Constants.java b/src/main/java/com/supwisdom/dlpay/framework/util/Constants.java
index c2e8555..17dd6bc 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/util/Constants.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/util/Constants.java
@@ -2,7 +2,7 @@
 
 public class Constants {
   //  HTTP HEADER define
-  public static final String HEADER_TETANTID = "TENANT-ID";
+  public static final String HEADER_TETANTID = "X-TENANT-ID";
 
   // define
   public static final String JWT_CLAIM_TENANTID = "tenantId";
diff --git a/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt b/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
index 3cfe781..430a8bd 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
@@ -1,15 +1,11 @@
 package com.supwisdom.dlpay
 
-import com.supwisdom.dlpay.system.common.DictPool
 import io.lettuce.core.ReadFrom
-import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.beans.factory.annotation.Value
 import org.springframework.boot.autoconfigure.SpringBootApplication
-import org.springframework.boot.context.event.ApplicationPreparedEvent
 import org.springframework.boot.runApplication
 import org.springframework.context.annotation.Bean
 import org.springframework.context.annotation.Configuration
-import org.springframework.context.event.EventListener
 import org.springframework.data.redis.connection.RedisConnectionFactory
 import org.springframework.data.redis.connection.RedisPassword
 import org.springframework.data.redis.connection.RedisStandaloneConfiguration
diff --git a/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt b/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
index 2304b37..393b5fb 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
@@ -64,7 +64,7 @@
 
     @GetMapping(value = ["/gettoken", "/gettoken/{clientid}"])
     fun loginInit(appid: String, @PathVariable clientid: String?,
-                  @RequestHeader(Constants.HEADER_TETANTID) tetantId: String): ResponseEntity<Any> {
+                  @RequestHeader(Constants.HEADER_TETANTID) tetantId: String?): ResponseEntity<Any> {
 
         tetantConfigDao.default?.also {
             if (it.tenantId != tetantId) {
diff --git a/src/main/kotlin/com/supwisdom/dlpay/framework/tenant.kt b/src/main/kotlin/com/supwisdom/dlpay/framework/tenant.kt
new file mode 100644
index 0000000..2990f19
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/framework/tenant.kt
@@ -0,0 +1,24 @@
+package com.supwisdom.dlpay.framework
+
+import com.supwisdom.dlpay.framework.util.Constants
+import org.springframework.core.annotation.Order
+import javax.servlet.Filter
+import javax.servlet.FilterChain
+import javax.servlet.ServletRequest
+import javax.servlet.ServletResponse
+import javax.servlet.annotation.WebFilter
+import javax.servlet.http.HttpServletRequest
+
+
+@Order(1)
+@WebFilter(filterName = "multi_tenant_filter", urlPatterns = ["/*"])
+class TenantNameFilter : Filter {
+    override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
+        if (request is HttpServletRequest) {
+            request.getHeader(Constants.HEADER_TETANTID)?.also {
+                // set tanent datasource
+            }
+        }
+        chain.doFilter(request, response)
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/supwisdom/dlpay/security.kt b/src/main/kotlin/com/supwisdom/dlpay/security.kt
index 8cf8e9f..d898fb7 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/security.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/security.kt
@@ -98,7 +98,7 @@
                     return
                 }
                 val claims = getUtil().verifyToken(jwt)
-                if(url.equals("/mobileapi/logout")){
+                if(url == "/mobileapi/logout"){
                     SecurityContextHolder.clearContext()
                     apiJwtRepository.deleteById(claims[ReservedClaimNames.JWT_ID].toString())
                     throw JoseException("JWT has not been register")
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 18ea9d2..4beb006 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -14,6 +14,7 @@
 #################### JSP PAGE ####################
 #spring.mvc.view.prefix=/pages/
 #spring.mvc.view.suffix=.jsp
+server.servlet.context-path=/payapi
 #################### thymeleaf ####################
 spring.mvc.static-path-pattern=/static/**
 spring.thymeleaf.prefix=classpath:/templates/
diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql
index 262c0c1..a1161f6 100644
--- a/src/main/resources/import.sql
+++ b/src/main/resources/import.sql
@@ -1,3 +1,6 @@
+INSERT INTO tb_tenantconfig(cfgid, tenantid, datacenter_id)
+values ('main', '10000110', '01');
+
 INSERT INTO tb_operator(operid, closedate, opendate, opercode, opername, operpwd, opertype, status)
 VALUES ('LOR2IwRkbOjp+sVG9KR2BpHZbwGKepS4', '20500101', '20190101', 'system', '系统管理员', '$2a$10$Ex9xp11.vCaD8D0a7ahiUOKqDij1TcCUBwRAmrqXeDvAkmzLibn4.', 'oper', 'normal');