yonge 3 years ago
parent
commit
953449a4f8
27 changed files with 1189 additions and 15 deletions
  1. 5 0
      cms/pom.xml
  2. 14 0
      cms/src/main/java/com/ym/mec/cms/config/WebMvcConfig.java
  3. 9 0
      cms/src/main/java/com/ym/mec/cms/dal/dao/TenantInfoDao.java
  4. 125 0
      cms/src/main/java/com/ym/mec/cms/dal/entity/TenantInfo.java
  5. 49 0
      cms/src/main/java/com/ym/mec/cms/interceptor/TenantInterceptor.java
  6. 8 0
      cms/src/main/java/com/ym/mec/cms/service/TenantInfoService.java
  7. 23 0
      cms/src/main/java/com/ym/mec/cms/service/impl/TenantInfoServiceImpl.java
  8. 94 0
      cms/src/main/resources/config/mybatis/TenantInfoMapper.xml
  9. 36 0
      dynamic-datasource/pom.xml
  10. 64 0
      dynamic-datasource/src/main/java/com/yonge/datasource/DataSourceConfig.java
  11. 46 0
      dynamic-datasource/src/main/java/com/yonge/datasource/DataSourceContextHolder.java
  12. 22 0
      dynamic-datasource/src/main/java/com/yonge/datasource/DynamicRoutingDataSource.java
  13. 56 0
      dynamic-datasource/src/main/java/com/yonge/datasource/dao/DatabaseSourceDao.java
  14. 125 0
      dynamic-datasource/src/main/java/com/yonge/datasource/entity/DatabaseSource.java
  15. 36 0
      dynamic-datasource/src/main/java/com/yonge/datasource/interceptor/DataSourceInterceptor.java
  16. 6 0
      dynamic-datasource/src/main/java/com/yonge/datasource/service/DatabaseSourceService.java
  17. 63 0
      dynamic-datasource/src/main/java/com/yonge/datasource/service/impl/DatabaseSourceServiceImpl.java
  18. 95 0
      dynamic-datasource/src/main/resources/config/mybatis/DatabaseSourceMapper.xml
  19. 11 0
      mec-auth/mec-auth-api/src/main/java/com/ym/mec/auth/api/entity/SysUser.java
  20. 1 12
      mec-auth/mec-auth-server/src/main/java/com/ym/mec/auth/core/handler/BaseAuthenticationSuccessEventHandler.java
  21. 9 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/TenantInfoDao.java
  22. 125 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/TenantInfo.java
  23. 8 0
      mec-biz/src/main/java/com/ym/mec/biz/service/TenantInfoService.java
  24. 23 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/TenantInfoServiceImpl.java
  25. 94 0
      mec-biz/src/main/resources/config/mybatis/TenantInfoMapper.xml
  26. 33 0
      mec-common/common-core/src/main/java/com/ym/mec/common/tenant/TenantContextHolder.java
  27. 9 3
      pom.xml

+ 5 - 0
cms/pom.xml

@@ -67,6 +67,11 @@
 			<groupId>com.yonge.log</groupId>
 			<artifactId>audit-log</artifactId>
 		</dependency>
+		
+		<dependency>
+			<groupId>com.yonge.datasource</groupId>
+			<artifactId>dynamic-datasource</artifactId>
+		</dependency>
 	</dependencies>
 	
 	<build>

+ 14 - 0
cms/src/main/java/com/ym/mec/cms/config/WebMvcConfig.java

@@ -13,8 +13,10 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 import com.ym.mec.cms.interceptor.OperationLogInterceptor;
+import com.ym.mec.cms.interceptor.TenantInterceptor;
 import com.ym.mec.common.config.EnumConverterFactory;
 import com.ym.mec.common.config.LocalFastJsonHttpMessageConverter;
+import com.yonge.datasource.interceptor.DataSourceInterceptor;
 
 @Configuration
 public class WebMvcConfig implements WebMvcConfigurer {
@@ -32,10 +34,22 @@ public class WebMvcConfig implements WebMvcConfigurer {
 	
 	@Override
 	public void addInterceptors(InterceptorRegistry registry) {
+		registry.addInterceptor(getTenantInterceptor()).addPathPatterns("/**");
+		registry.addInterceptor(getDataSrouceInterceptor()).addPathPatterns("/**");
 		registry.addInterceptor(operationLogInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
 	}
 
 	@Bean
+	public DataSourceInterceptor getDataSrouceInterceptor() {
+		return new DataSourceInterceptor();
+	}
+
+	@Bean
+	public TenantInterceptor getTenantInterceptor() {
+		return new TenantInterceptor();
+	}
+
+	@Bean
     public HttpMessageConverters fastJsonHttpMessageConverters(){
 		LocalFastJsonHttpMessageConverter converter = new LocalFastJsonHttpMessageConverter();
         List<MediaType> fastMediaTypes =  new ArrayList<MediaType>();

+ 9 - 0
cms/src/main/java/com/ym/mec/cms/dal/dao/TenantInfoDao.java

@@ -0,0 +1,9 @@
+package com.ym.mec.cms.dal.dao;
+
+import com.ym.mec.cms.dal.entity.TenantInfo;
+import com.ym.mec.common.dal.BaseDAO;
+
+public interface TenantInfoDao extends BaseDAO<Integer, TenantInfo> {
+
+	
+}

+ 125 - 0
cms/src/main/java/com/ym/mec/cms/dal/entity/TenantInfo.java

@@ -0,0 +1,125 @@
+package com.ym.mec.cms.dal.entity;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+/**
+ * 对应数据库表(tenant_info):
+ */
+public class TenantInfo {
+
+	/**  */
+	private Integer id;
+	
+	/** 机构名称 */
+	private String name;
+	
+	/** 机构地址 */
+	private String address;
+	
+	/** 域名 */
+	private String domainName;
+	
+	/** logo链接 */
+	private String logoUrl;
+	
+	/** 联系人 */
+	private String contactName;
+	
+	/** 联系电话 */
+	private String contactPhone;
+	
+	/** 数据源 */
+	private String dataSource;
+	
+	/**  */
+	private java.util.Date createTime;
+	
+	/**  */
+	private java.util.Date updateTime;
+	
+	public void setId(Integer id){
+		this.id = id;
+	}
+	
+	public Integer getId(){
+		return this.id;
+	}
+			
+	public void setName(String name){
+		this.name = name;
+	}
+	
+	public String getName(){
+		return this.name;
+	}
+			
+	public void setAddress(String address){
+		this.address = address;
+	}
+	
+	public String getAddress(){
+		return this.address;
+	}
+			
+	public void setDomainName(String domainName){
+		this.domainName = domainName;
+	}
+	
+	public String getDomainName(){
+		return this.domainName;
+	}
+			
+	public void setLogoUrl(String logoUrl){
+		this.logoUrl = logoUrl;
+	}
+	
+	public String getLogoUrl(){
+		return this.logoUrl;
+	}
+			
+	public void setContactName(String contactName){
+		this.contactName = contactName;
+	}
+	
+	public String getContactName(){
+		return this.contactName;
+	}
+			
+	public void setContactPhone(String contactPhone){
+		this.contactPhone = contactPhone;
+	}
+	
+	public String getContactPhone(){
+		return this.contactPhone;
+	}
+			
+	public void setDataSource(String dataSource){
+		this.dataSource = dataSource;
+	}
+	
+	public String getDataSource(){
+		return this.dataSource;
+	}
+			
+	public void setCreateTime(java.util.Date createTime){
+		this.createTime = createTime;
+	}
+	
+	public java.util.Date getCreateTime(){
+		return this.createTime;
+	}
+			
+	public void setUpdateTime(java.util.Date updateTime){
+		this.updateTime = updateTime;
+	}
+	
+	public java.util.Date getUpdateTime(){
+		return this.updateTime;
+	}
+			
+	@Override
+	public String toString() {
+		return ToStringBuilder.reflectionToString(this);
+	}
+
+}

+ 49 - 0
cms/src/main/java/com/ym/mec/cms/interceptor/TenantInterceptor.java

@@ -0,0 +1,49 @@
+package com.ym.mec.cms.interceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.cms.dal.entity.TenantInfo;
+import com.ym.mec.cms.service.TenantInfoService;
+import com.ym.mec.common.tenant.TenantContextHolder;
+
+public class TenantInterceptor extends HandlerInterceptorAdapter {
+
+	private static final String DATA_SOURCE_ID = "datasourceId";
+
+	@Autowired
+	@Lazy
+	private SysUserFeignService sysUserFeignService;
+	
+	@Autowired
+	private TenantInfoService tenantInfoService;
+
+	@Override
+	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+		
+		SysUser sysUser = sysUserFeignService.queryUserInfo();
+		
+		if(sysUser != null){
+			TenantContextHolder.setTenantId(sysUser.getTenantId() + "");
+			
+			TenantInfo tenantInfo = tenantInfoService.get(sysUser.getTenantId());
+			if(tenantInfo != null){
+				request.setAttribute(DATA_SOURCE_ID, tenantInfo.getDataSource());
+			}
+		}
+		
+		return true;
+	}
+
+	@Override
+	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+		TenantContextHolder.clearTenantId();
+	}
+
+}

+ 8 - 0
cms/src/main/java/com/ym/mec/cms/service/TenantInfoService.java

@@ -0,0 +1,8 @@
+package com.ym.mec.cms.service;
+
+import com.ym.mec.cms.dal.entity.TenantInfo;
+import com.ym.mec.common.service.BaseService;
+
+public interface TenantInfoService extends BaseService<Integer, TenantInfo> {
+
+}

+ 23 - 0
cms/src/main/java/com/ym/mec/cms/service/impl/TenantInfoServiceImpl.java

@@ -0,0 +1,23 @@
+package com.ym.mec.cms.service.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.ym.mec.cms.dal.dao.TenantInfoDao;
+import com.ym.mec.cms.dal.entity.TenantInfo;
+import com.ym.mec.cms.service.TenantInfoService;
+import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.common.service.impl.BaseServiceImpl;
+
+@Service
+public class TenantInfoServiceImpl extends BaseServiceImpl<Integer, TenantInfo>  implements TenantInfoService {
+	
+	@Autowired
+	private TenantInfoDao tenantInfoDao;
+
+	@Override
+	public BaseDAO<Integer, TenantInfo> getDAO() {
+		return tenantInfoDao;
+	}
+	
+}

+ 94 - 0
cms/src/main/resources/config/mybatis/TenantInfoMapper.xml

@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<!-- 这个文件是自动生成的。 不要修改此文件。所有改动将在下次重新自动生成时丢失。 -->
+<mapper namespace="com.ym.mec.cms.dal.dao.TenantInfoDao">
+
+	<resultMap type="com.ym.mec.cms.dal.entity.TenantInfo" id="TenantInfo">
+		<result column="id_" property="id" />
+		<result column="name_" property="name" />
+		<result column="address_" property="address" />
+		<result column="domain_name_" property="domainName" />
+		<result column="logo_url_" property="logoUrl" />
+		<result column="contact_name_" property="contactName" />
+		<result column="contact_phone_" property="contactPhone" />
+		<result column="data_source_" property="dataSource" />
+		<result column="create_time_" property="createTime" />
+		<result column="update_time_" property="updateTime" />
+	</resultMap>
+
+	<!-- 根据主键查询一条记录 -->
+	<select id="get" resultMap="TenantInfo">
+		SELECT * FROM
+		tenant_info WHERE id_ = #{id}
+	</select>
+
+	<!-- 全查询 -->
+	<select id="findAll" resultMap="TenantInfo">
+		SELECT * FROM tenant_info ORDER
+		BY id_
+	</select>
+
+	<!-- 向数据库增加一条记录 -->
+	<insert id="insert" parameterType="com.ym.mec.cms.dal.entity.TenantInfo"
+		useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+		<!-- <selectKey resultClass="int" keyProperty="id" > SELECT SEQ_WSDEFINITION_ID.nextval 
+			AS ID FROM DUAL </selectKey> -->
+		INSERT INTO tenant_info
+		(id_,name_,address_,domain_name_,logo_url_,contact_name_,contact_phone_,data_source_,create_time_,update_time_)
+		VALUES(#{id},#{name},#{address},#{domainName},#{logoUrl},#{contactName},#{contactPhone},#{dataSource},#{createTime},#{updateTime})
+	</insert>
+
+	<!-- 根据主键查询一条记录 -->
+	<update id="update" parameterType="com.ym.mec.cms.dal.entity.TenantInfo">
+		UPDATE tenant_info
+		<set>
+			<if test="address != null">
+				address_ = #{address},
+			</if>
+			<if test="dataSource != null">
+				data_source_ = #{dataSource},
+			</if>
+			<if test="id != null">
+				id_ = #{id},
+			</if>
+			<if test="updateTime != null">
+				update_time_ = #{updateTime},
+			</if>
+			<if test="logoUrl != null">
+				logo_url_ = #{logoUrl},
+			</if>
+			<if test="contactPhone != null">
+				contact_phone_ = #{contactPhone},
+			</if>
+			<if test="domainName != null">
+				domain_name_ = #{domainName},
+			</if>
+			<if test="contactName != null">
+				contact_name_ = #{contactName},
+			</if>
+			<if test="name != null">
+				name_ = #{name},
+			</if>
+			<if test="createTime != null">
+				create_time_ = #{createTime},
+			</if>
+		</set>
+		WHERE id_ = #{id}
+	</update>
+
+	<!-- 根据主键删除一条记录 -->
+	<delete id="delete">
+		DELETE FROM tenant_info WHERE id_ = #{id}
+	</delete>
+
+	<!-- 分页查询 -->
+	<select id="queryPage" resultMap="TenantInfo" parameterType="map">
+		SELECT * FROM tenant_info ORDER BY id_
+		<include refid="global.limit" />
+	</select>
+
+	<!-- 查询当前表的总记录数 -->
+	<select id="queryCount" resultType="int">
+		SELECT COUNT(*) FROM tenant_info
+	</select>
+</mapper>

+ 36 - 0
dynamic-datasource/pom.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.ym</groupId>
+    <artifactId>mec</artifactId>
+    <version>1.0</version>
+  </parent>
+  <groupId>com.yonge.datasource</groupId>
+  <artifactId>dynamic-datasource</artifactId>
+  <version>1.0</version>
+  <name>dynamic-datasource</name>
+  <url>http://maven.apache.org</url>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+  <dependencies>
+
+		<dependency>
+			<groupId>org.mybatis.spring.boot</groupId>
+			<artifactId>mybatis-spring-boot-starter</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>druid-spring-boot-starter</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>javax.servlet-api</artifactId>
+		</dependency>
+		
+  </dependencies>
+</project>

+ 64 - 0
dynamic-datasource/src/main/java/com/yonge/datasource/DataSourceConfig.java

@@ -0,0 +1,64 @@
+package com.yonge.datasource;
+
+import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.sql.DataSource;
+import java.util.HashMap;
+import java.util.Map;
+
+@EnableTransactionManagement
+@Configuration
+@MapperScan("com.keao.edu.datasource.dao")
+public class DataSourceConfig {
+
+	@Value("${mybatis.mapperLocations}")
+	private String resourcePath;
+	@Value("${mybatis.typeAliasesPackage}")
+	private String typeAliasesPackage;
+
+	@Bean("master")
+	@Primary
+	@ConfigurationProperties(prefix = "spring.datasource") // application.yml中对应属性的前缀
+	public DataSource master() {
+		return DruidDataSourceBuilder.create().build();
+	}
+
+	@Bean("dynamicDataSource")
+	public DataSource dynamicDataSource() {
+		DynamicRoutingDataSource dynamicDataSource = new DynamicRoutingDataSource();
+		Map<Object, Object> dataSourceMap = new HashMap<>();
+		dataSourceMap.put("master", master());
+		// 将 master 数据源作为默认指定的数据源
+		dynamicDataSource.setDefaultTargetDataSource(master());
+		dynamicDataSource.setTargetDataSources(dataSourceMap);
+		return dynamicDataSource;
+	}
+	@Bean
+	public SqlSessionFactoryBean sqlSessionFactoryBean() throws Exception {
+		SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
+		// 配置动态数据源,如果没有将 dynamicDataSource 作为数据源则不能实现切换
+		sqlSessionFactoryBean.setDataSource(dynamicDataSource());
+		sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(resourcePath));
+		sqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
+
+		return sqlSessionFactoryBean;
+	}
+
+	@Bean
+	public PlatformTransactionManager transactionManager() {
+		// 配置事务管理, 使用事务时在方法头部添加@Transactional注解即可
+		return new DataSourceTransactionManager(dynamicDataSource());
+	}
+
+}

+ 46 - 0
dynamic-datasource/src/main/java/com/yonge/datasource/DataSourceContextHolder.java

@@ -0,0 +1,46 @@
+package com.yonge.datasource;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class DataSourceContextHolder {
+	
+	public final static String TENANT_ID = "master";
+
+	private static final ThreadLocal<Object> contextHolder = new ThreadLocal<Object>() {
+		@Override
+		protected String initialValue() {
+			return TENANT_ID;
+		}
+	};
+
+	public static List<Object> dataSourceKeys = new ArrayList<Object>();
+
+	public static void setDataSourceKey(String key) {
+		contextHolder.set(key);
+	}
+
+	/**
+	 * 获取数据源
+	 * @return
+	 */
+	public static Object getDataSourceKey() {
+		return contextHolder.get();
+	}
+
+	/**
+	 * 重置数据源
+	 */
+	public static void clearDataSourceKey() {
+		contextHolder.remove();
+	}
+
+	public static boolean containDataSourceKey(Object key) {
+		return dataSourceKeys.contains(key);
+	}
+
+	public static boolean addDataSourceKeys(Collection<? extends Object> keys) {
+		return dataSourceKeys.addAll(keys);
+	}
+}

+ 22 - 0
dynamic-datasource/src/main/java/com/yonge/datasource/DynamicRoutingDataSource.java

@@ -0,0 +1,22 @@
+package com.yonge.datasource;
+
+import java.util.Map;
+
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
+
+	@Override
+	protected Object determineCurrentLookupKey() {
+		return DataSourceContextHolder.getDataSourceKey();
+	}
+
+	@Override
+	public void setTargetDataSources(Map<Object, Object> targetDataSources) {
+		super.setTargetDataSources(targetDataSources);
+		
+		// 将数据源的 key 放到数据源上下文的 key 集合中
+		DataSourceContextHolder.addDataSourceKeys(targetDataSources.keySet());
+	}
+
+}

+ 56 - 0
dynamic-datasource/src/main/java/com/yonge/datasource/dao/DatabaseSourceDao.java

@@ -0,0 +1,56 @@
+package com.yonge.datasource.dao;
+
+import java.util.List;
+import java.util.Map;
+
+import com.yonge.datasource.entity.DatabaseSource;
+
+
+public interface DatabaseSourceDao  {
+
+	/**
+	 * 通过主键id获取对象
+	 * @param id
+	 * @return DatabaseSource
+	 */
+	public DatabaseSource geDatabaseSource(final Integer id);
+
+	/**
+	 * 更新实体对象
+	 * @param bean
+	 * @return inDatabaseSource
+	 */
+	public int updaDatabaseSourcee(DatabaseSource bean);
+
+	/**
+	 * 通过主键id删除对象
+	 * @param id
+	 * @return inDatabaseSource
+	 */
+	public int deleDatabaseSourcee(final Integer id);
+	
+	/**
+	 * 写入实体对象
+	 * @param bean
+	 * @return inDatabaseSource
+	 */
+	public long inserDatabaseSource(DatabaseSource bean);
+	/**
+	 * 通过参数查找所有结果集
+	 * @param params
+	 * @return
+	 */
+	public List<DatabaseSource> findAll(Map<String, Object> params);
+	/**
+	 * 通过参数查找结果集,适合分页场景
+	 * @param params
+	 * @return
+	 */
+	public List<DatabaseSource> queryPage(Map<String, Object> params);
+	/**
+	 * 通过参数查找结果集数目
+	 * @param params
+	 * @return
+	 */
+	public int queryCounDatabaseSource(Map<String, Object> params);
+}

+ 125 - 0
dynamic-datasource/src/main/java/com/yonge/datasource/entity/DatabaseSource.java

@@ -0,0 +1,125 @@
+package com.yonge.datasource.entity;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+/**
+ * 对应数据库表(database_source):
+ */
+public class DatabaseSource {
+
+	/**  */
+	private Integer id;
+	
+	/** 租户ID */
+	private String tenantId;
+	
+	/** 驱动 */
+	private String driver;
+	
+	/** 连接信息 */
+	private String url;
+	
+	/** 用户名 */
+	private String username;
+	
+	/** 密码 */
+	private String password;
+	
+	/** 数据库类型 */
+	private String type;
+	
+	/**  */
+	private String memo;
+	
+	/**  */
+	private java.util.Date createTime;
+	
+	/**  */
+	private java.util.Date updateTime;
+	
+	public void setId(Integer id){
+		this.id = id;
+	}
+	
+	public Integer getId(){
+		return this.id;
+	}
+			
+	public void setTenantId(String tenantId){
+		this.tenantId = tenantId;
+	}
+	
+	public String getTenantId(){
+		return this.tenantId;
+	}
+			
+	public void setDriver(String driver){
+		this.driver = driver;
+	}
+	
+	public String getDriver(){
+		return this.driver;
+	}
+			
+	public void setUrl(String url){
+		this.url = url;
+	}
+	
+	public String getUrl(){
+		return this.url;
+	}
+			
+	public void setUsername(String username){
+		this.username = username;
+	}
+	
+	public String getUsername(){
+		return this.username;
+	}
+			
+	public void setPassword(String password){
+		this.password = password;
+	}
+	
+	public String getPassword(){
+		return this.password;
+	}
+			
+	public void setType(String type){
+		this.type = type;
+	}
+	
+	public String getType(){
+		return this.type;
+	}
+			
+	public void setMemo(String memo){
+		this.memo = memo;
+	}
+	
+	public String getMemo(){
+		return this.memo;
+	}
+			
+	public void setCreateTime(java.util.Date createTime){
+		this.createTime = createTime;
+	}
+	
+	public java.util.Date getCreateTime(){
+		return this.createTime;
+	}
+			
+	public void setUpdateTime(java.util.Date updateTime){
+		this.updateTime = updateTime;
+	}
+	
+	public java.util.Date getUpdateTime(){
+		return this.updateTime;
+	}
+			
+	@Override
+	public String toString() {
+		return ToStringBuilder.reflectionToString(this);
+	}
+
+}

+ 36 - 0
dynamic-datasource/src/main/java/com/yonge/datasource/interceptor/DataSourceInterceptor.java

@@ -0,0 +1,36 @@
+package com.yonge.datasource.interceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import com.yonge.datasource.DataSourceContextHolder;
+
+public class DataSourceInterceptor extends HandlerInterceptorAdapter {
+
+	private static final String DATA_SOURCE_ID = "datasourceId";
+
+	@Override
+	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+		String tenantId = request.getHeader(DATA_SOURCE_ID);
+		if (StringUtils.isBlank(tenantId)) {
+			tenantId = request.getParameter(DATA_SOURCE_ID);
+		}
+		if (StringUtils.isBlank(tenantId)) {
+			tenantId = (String) request.getAttribute(DATA_SOURCE_ID);
+		}
+		if(StringUtils.isNotBlank(tenantId)){
+			DataSourceContextHolder.setDataSourceKey(tenantId);
+		}
+
+		return true;
+	}
+
+	@Override
+	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+		DataSourceContextHolder.clearDataSourceKey();
+	}
+
+}

+ 6 - 0
dynamic-datasource/src/main/java/com/yonge/datasource/service/DatabaseSourceService.java

@@ -0,0 +1,6 @@
+package com.yonge.datasource.service;
+
+
+public interface DatabaseSourceService {
+	
+}

+ 63 - 0
dynamic-datasource/src/main/java/com/yonge/datasource/service/impl/DatabaseSourceServiceImpl.java

@@ -0,0 +1,63 @@
+package com.yonge.datasource.service.impl;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Service;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.yonge.datasource.DynamicRoutingDataSource;
+import com.yonge.datasource.dao.DatabaseSourceDao;
+import com.yonge.datasource.entity.DatabaseSource;
+import com.yonge.datasource.service.DatabaseSourceService;
+
+@Service
+public class DatabaseSourceServiceImpl implements DatabaseSourceService, ApplicationContextAware,
+		InitializingBean {
+	
+	private final static String DEFAULT_DATA_SOURCE_KEY = "master";
+
+	@Autowired
+	private DatabaseSourceDao databaseSourceDao;
+
+	private ApplicationContext applicationContext;
+
+	@Override
+	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+		this.applicationContext = applicationContext;
+	}
+
+	@Override
+	public void afterPropertiesSet() throws Exception {
+
+		DynamicRoutingDataSource dynamicDataSource = (DynamicRoutingDataSource) applicationContext.getBean("dynamicDataSource");
+		DruidDataSource master = (DruidDataSource) applicationContext.getBean(DEFAULT_DATA_SOURCE_KEY);
+		Map<Object, Object> dataSourceMap = new HashMap<>();
+		dataSourceMap.put("master", master);
+
+		List<DatabaseSource> dbSourceList = databaseSourceDao.findAll(null);
+		for (DatabaseSource ds : dbSourceList) {
+			DruidDataSource dataSource = new DruidDataSource();
+
+			dataSource.setDriverClassName(ds.getDriver());
+			dataSource.setUrl(ds.getUrl());
+			dataSource.setUsername(ds.getUsername());
+			dataSource.setPassword(ds.getPassword());
+			dataSource.setConnectProperties(master.getConnectProperties());
+
+			dataSourceMap.put(ds.getTenantId(), dataSource);
+		}
+
+		dynamicDataSource.setTargetDataSources(dataSourceMap);
+
+		// 必须执行此操作,才会重新初始化AbstractRoutingDataSource 中的 resolvedDataSources,也只有这样,动态切换才会起效
+		dynamicDataSource.afterPropertiesSet();
+	}
+
+}

+ 95 - 0
dynamic-datasource/src/main/resources/config/mybatis/DatabaseSourceMapper.xml

@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<!-- 这个文件是自动生成的。 不要修改此文件。所有改动将在下次重新自动生成时丢失。 -->
+<mapper namespace="com.keao.edu.datasource.dao.DatabaseSourceDao">
+
+	<resultMap type="com.keao.edu.datasource.entity.DatabaseSource"
+		id="DatabaseSource">
+		<result column="id_" property="id" />
+		<result column="tenant_id_" property="tenantId" />
+		<result column="driver_" property="driver" />
+		<result column="url_" property="url" />
+		<result column="username_" property="username" />
+		<result column="password_" property="password" />
+		<result column="type_" property="type" />
+		<result column="memo_" property="memo" />
+		<result column="create_time_" property="createTime" />
+		<result column="update_time_" property="updateTime" />
+	</resultMap>
+
+	<!-- 根据主键查询一条记录 -->
+	<select id="get" resultMap="DatabaseSource">
+		SELECT * FROM
+		database_source WHERE id_ = #{id}
+	</select>
+
+	<!-- 全查询 -->
+	<select id="findAll" resultMap="DatabaseSource">
+		SELECT * FROM database_source
+		ORDER BY id_
+	</select>
+
+	<!-- 向数据库增加一条记录 -->
+	<insert id="insert" parameterType="com.keao.edu.datasource.entity.DatabaseSource"
+		useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+		<!-- <selectKey resultClass="int" keyProperty="id" > SELECT SEQ_WSDEFINITION_ID.nextval 
+			AS ID FROM DUAL </selectKey> -->
+		INSERT INTO database_source
+		(id_,tenant_id_,driver_,url_,username_,password_,type_,memo_,create_time_,update_time_)
+		VALUES(#{id},#{tenantId},#{driver},#{url},#{username},#{password},#{type},#{memo},#{createTime},#{updateTime})
+	</insert>
+
+	<!-- 根据主键查询一条记录 -->
+	<update id="update" parameterType="com.keao.edu.datasource.entity.DatabaseSource">
+		UPDATE database_source
+		<set>
+			<if test="driver != null">
+				driver_ = #{driver},
+			</if>
+			<if test="id != null">
+				id_ = #{id},
+			</if>
+			<if test="tenantId != null and tenantId != 0">
+				tenant_id_ = #{tenantId},
+			</if>
+			<if test="url != null">
+				url_ = #{url},
+			</if>
+			<if test="updateTime != null">
+				update_time_ = #{updateTime},
+			</if>
+			<if test="password != null">
+				password_ = #{password},
+			</if>
+			<if test="memo != null">
+				memo_ = #{memo},
+			</if>
+			<if test="username != null">
+				username_ = #{username},
+			</if>
+			<if test="type != null">
+				type_ = #{type},
+			</if>
+			<if test="createTime != null">
+				create_time_ = #{createTime},
+			</if>
+		</set>
+		WHERE id_ = #{id}
+	</update>
+
+	<!-- 根据主键删除一条记录 -->
+	<delete id="delete">
+		DELETE FROM database_source WHERE id_ =
+		#{id}
+	</delete>
+
+	<!-- 分页查询 -->
+	<select id="queryPage" resultMap="DatabaseSource" parameterType="map">
+		SELECT * FROM database_source ORDER BY id_
+	</select>
+
+	<!-- 查询当前表的总记录数 -->
+	<select id="queryCount" resultType="int">
+		SELECT COUNT(*) FROM database_source
+	</select>
+</mapper>

+ 11 - 0
mec-auth/mec-auth-api/src/main/java/com/ym/mec/auth/api/entity/SysUser.java

@@ -23,6 +23,9 @@ public class SysUser implements Serializable{
 
 	/** 主键ID */
 	private Integer id;
+	
+	/** 机构编号 */
+	private Integer tenantId;
 
 	/** 用户名 */
 	@ApiModelProperty(value = "用户名",required = false)
@@ -225,6 +228,14 @@ public class SysUser implements Serializable{
 		this.id = id;
 	}
 
+	public Integer getTenantId() {
+		return tenantId;
+	}
+
+	public void setTenantId(Integer tenantId) {
+		this.tenantId = tenantId;
+	}
+
 	public void setUsername(String username) {
 		this.username = username;
 	}

+ 1 - 12
mec-auth/mec-auth-server/src/main/java/com/ym/mec/auth/core/handler/BaseAuthenticationSuccessEventHandler.java

@@ -150,19 +150,8 @@ public class BaseAuthenticationSuccessEventHandler extends SavedRequestAwareAuth
 				}
 			}
 			map.put("tenantId", tenantId);
+			map.put("companyId", sysUser.getTenantId());
 
-			/*map.put("isLessee",false);
-			if("TEACHER".equals(clientId.toUpperCase())){
-				Integer organId = sysUserService.getTeacherOrganId(sysUser.getId());
-				if(organId != null && organId == lesseeOrganId){
-					map.put("isLessee",true);
-				}
-			}else if("STUDENT".equals(clientId.toUpperCase())){
-				if(sysUser.getOrganId() == lesseeOrganId){
-					map.put("isLessee",true);
-				}
-			}*/
-			
 			response.setContentType("application/json; charset=utf-8");
 			HttpResponseResult result = new HttpResponseResult(true, HttpStatus.OK.value(), map, "");
 			response.getWriter().write(objectMapper.writeValueAsString(result));

+ 9 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/TenantInfoDao.java

@@ -0,0 +1,9 @@
+package com.ym.mec.biz.dal.dao;
+
+import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.biz.dal.entity.TenantInfo;
+
+public interface TenantInfoDao extends BaseDAO<Integer, TenantInfo> {
+
+	
+}

+ 125 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/TenantInfo.java

@@ -0,0 +1,125 @@
+package com.ym.mec.biz.dal.entity;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+/**
+ * 对应数据库表(tenant_info):
+ */
+public class TenantInfo {
+
+	/**  */
+	private Integer id;
+	
+	/** 机构名称 */
+	private String name;
+	
+	/** 机构地址 */
+	private String address;
+	
+	/** 域名 */
+	private String domainName;
+	
+	/** logo链接 */
+	private String logoUrl;
+	
+	/** 联系人 */
+	private String contactName;
+	
+	/** 联系电话 */
+	private String contactPhone;
+	
+	/** 数据源 */
+	private String dataSource;
+	
+	/**  */
+	private java.util.Date createTime;
+	
+	/**  */
+	private java.util.Date updateTime;
+	
+	public void setId(Integer id){
+		this.id = id;
+	}
+	
+	public Integer getId(){
+		return this.id;
+	}
+			
+	public void setName(String name){
+		this.name = name;
+	}
+	
+	public String getName(){
+		return this.name;
+	}
+			
+	public void setAddress(String address){
+		this.address = address;
+	}
+	
+	public String getAddress(){
+		return this.address;
+	}
+			
+	public void setDomainName(String domainName){
+		this.domainName = domainName;
+	}
+	
+	public String getDomainName(){
+		return this.domainName;
+	}
+			
+	public void setLogoUrl(String logoUrl){
+		this.logoUrl = logoUrl;
+	}
+	
+	public String getLogoUrl(){
+		return this.logoUrl;
+	}
+			
+	public void setContactName(String contactName){
+		this.contactName = contactName;
+	}
+	
+	public String getContactName(){
+		return this.contactName;
+	}
+			
+	public void setContactPhone(String contactPhone){
+		this.contactPhone = contactPhone;
+	}
+	
+	public String getContactPhone(){
+		return this.contactPhone;
+	}
+			
+	public void setDataSource(String dataSource){
+		this.dataSource = dataSource;
+	}
+	
+	public String getDataSource(){
+		return this.dataSource;
+	}
+			
+	public void setCreateTime(java.util.Date createTime){
+		this.createTime = createTime;
+	}
+	
+	public java.util.Date getCreateTime(){
+		return this.createTime;
+	}
+			
+	public void setUpdateTime(java.util.Date updateTime){
+		this.updateTime = updateTime;
+	}
+	
+	public java.util.Date getUpdateTime(){
+		return this.updateTime;
+	}
+			
+	@Override
+	public String toString() {
+		return ToStringBuilder.reflectionToString(this);
+	}
+
+}

+ 8 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/TenantInfoService.java

@@ -0,0 +1,8 @@
+package com.ym.mec.biz.service;
+
+import com.ym.mec.biz.dal.entity.TenantInfo;
+import com.ym.mec.common.service.BaseService;
+
+public interface TenantInfoService extends BaseService<Integer, TenantInfo> {
+
+}

+ 23 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/TenantInfoServiceImpl.java

@@ -0,0 +1,23 @@
+package com.ym.mec.biz.service.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.ym.mec.biz.dal.dao.TenantInfoDao;
+import com.ym.mec.biz.dal.entity.TenantInfo;
+import com.ym.mec.biz.service.TenantInfoService;
+import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.common.service.impl.BaseServiceImpl;
+
+@Service
+public class TenantInfoServiceImpl extends BaseServiceImpl<Integer, TenantInfo>  implements TenantInfoService {
+	
+	@Autowired
+	private TenantInfoDao tenantInfoDao;
+
+	@Override
+	public BaseDAO<Integer, TenantInfo> getDAO() {
+		return tenantInfoDao;
+	}
+	
+}

+ 94 - 0
mec-biz/src/main/resources/config/mybatis/TenantInfoMapper.xml

@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<!-- 这个文件是自动生成的。 不要修改此文件。所有改动将在下次重新自动生成时丢失。 -->
+<mapper namespace="com.ym.mec.biz.dal.dao.TenantInfoDao">
+
+	<resultMap type="com.ym.mec.biz.dal.entity.TenantInfo" id="TenantInfo">
+		<result column="id_" property="id" />
+		<result column="name_" property="name" />
+		<result column="address_" property="address" />
+		<result column="domain_name_" property="domainName" />
+		<result column="logo_url_" property="logoUrl" />
+		<result column="contact_name_" property="contactName" />
+		<result column="contact_phone_" property="contactPhone" />
+		<result column="data_source_" property="dataSource" />
+		<result column="create_time_" property="createTime" />
+		<result column="update_time_" property="updateTime" />
+	</resultMap>
+
+	<!-- 根据主键查询一条记录 -->
+	<select id="get" resultMap="TenantInfo">
+		SELECT * FROM
+		tenant_info WHERE id_ = #{id}
+	</select>
+
+	<!-- 全查询 -->
+	<select id="findAll" resultMap="TenantInfo">
+		SELECT * FROM tenant_info ORDER
+		BY id_
+	</select>
+
+	<!-- 向数据库增加一条记录 -->
+	<insert id="insert" parameterType="com.ym.mec.biz.dal.entity.TenantInfo"
+		useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+		<!-- <selectKey resultClass="int" keyProperty="id" > SELECT SEQ_WSDEFINITION_ID.nextval 
+			AS ID FROM DUAL </selectKey> -->
+		INSERT INTO tenant_info
+		(id_,name_,address_,domain_name_,logo_url_,contact_name_,contact_phone_,data_source_,create_time_,update_time_)
+		VALUES(#{id},#{name},#{address},#{domainName},#{logoUrl},#{contactName},#{contactPhone},#{dataSource},#{createTime},#{updateTime})
+	</insert>
+
+	<!-- 根据主键查询一条记录 -->
+	<update id="update" parameterType="com.ym.mec.biz.dal.entity.TenantInfo">
+		UPDATE tenant_info
+		<set>
+			<if test="address != null">
+				address_ = #{address},
+			</if>
+			<if test="dataSource != null">
+				data_source_ = #{dataSource},
+			</if>
+			<if test="id != null">
+				id_ = #{id},
+			</if>
+			<if test="updateTime != null">
+				update_time_ = #{updateTime},
+			</if>
+			<if test="logoUrl != null">
+				logo_url_ = #{logoUrl},
+			</if>
+			<if test="contactPhone != null">
+				contact_phone_ = #{contactPhone},
+			</if>
+			<if test="domainName != null">
+				domain_name_ = #{domainName},
+			</if>
+			<if test="contactName != null">
+				contact_name_ = #{contactName},
+			</if>
+			<if test="name != null">
+				name_ = #{name},
+			</if>
+			<if test="createTime != null">
+				create_time_ = #{createTime},
+			</if>
+		</set>
+		WHERE id_ = #{id}
+	</update>
+
+	<!-- 根据主键删除一条记录 -->
+	<delete id="delete">
+		DELETE FROM tenant_info WHERE id_ = #{id}
+	</delete>
+
+	<!-- 分页查询 -->
+	<select id="queryPage" resultMap="TenantInfo" parameterType="map">
+		SELECT * FROM tenant_info ORDER BY id_
+		<include refid="global.limit" />
+	</select>
+
+	<!-- 查询当前表的总记录数 -->
+	<select id="queryCount" resultType="int">
+		SELECT COUNT(*) FROM tenant_info
+	</select>
+</mapper>

+ 33 - 0
mec-common/common-core/src/main/java/com/ym/mec/common/tenant/TenantContextHolder.java

@@ -0,0 +1,33 @@
+package com.ym.mec.common.tenant;
+
+
+import org.apache.commons.lang3.StringUtils;
+
+public class TenantContextHolder {
+	
+
+	private static final ThreadLocal<String> tenantContextHolder = new ThreadLocal<String>();
+
+	public static void setTenantId(String tenantId) {
+		tenantContextHolder.set(tenantId);
+	}
+
+	/**
+	 * 获取数据源
+	 * @return
+	 */
+	public static String getTenantId() {
+		if (StringUtils.isEmpty(tenantContextHolder.get())){
+			return "0";
+		}
+		return tenantContextHolder.get();
+	}
+
+	/**
+	 * 重置数据源
+	 */
+	public static void clearTenantId() {
+		tenantContextHolder.remove();
+	}
+
+}

+ 9 - 3
pom.xml

@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 
 	<groupId>com.ym</groupId>
@@ -90,6 +89,12 @@
 			</dependency>
 		
 			<dependency>
+				<groupId>com.yonge.datasource</groupId>
+				<artifactId>dynamic-datasource</artifactId>
+				<version>1.0</version>
+			</dependency>
+		
+			<dependency>
 				<groupId>com.yonge.log</groupId>
 				<artifactId>audit-log</artifactId>
 				<version>1.0</version>
@@ -372,5 +377,6 @@
 		<module>mec-student</module>
 		<module>mec-teacher</module>
 		<module>mec-biz</module>
-	</modules>
+	  <module>dynamic-datasource</module>
+  </modules>
 </project>