add
This commit is contained in:
@ -35,7 +35,7 @@ public class SysTenant extends BaseEntity {
|
||||
/**
|
||||
* 数据库模式
|
||||
*/
|
||||
public static final String DATABASE_MODE = "2";
|
||||
public static final String SCHEMA_MODE = "2";
|
||||
|
||||
/**
|
||||
* 数据源模式
|
||||
|
@ -0,0 +1,36 @@
|
||||
package com.qiaoba.module.tenant.entity.param;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 租户数据源查询参数
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/6/9 13:18
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class SysTenantDatasourceParam implements Serializable {
|
||||
|
||||
private String tenantId;
|
||||
|
||||
private String isMaster;
|
||||
|
||||
private String isUse;
|
||||
|
||||
|
||||
public SysTenantDatasourceParam(String tenantId) {
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
|
||||
public SysTenantDatasourceParam(String tenantId, String isMaster) {
|
||||
this.tenantId = tenantId;
|
||||
this.isMaster = isMaster;
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
package com.qiaoba.module.tenant.filters;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.qiaoba.common.base.constants.TenantConstant;
|
||||
import com.qiaoba.common.base.context.BaseContext;
|
||||
import com.qiaoba.common.base.enums.BaseEnum;
|
||||
import com.qiaoba.common.database.config.DynamicDataSourceConfig;
|
||||
import com.qiaoba.common.database.constants.DynamicDatasourceConstant;
|
||||
import com.qiaoba.common.web.utils.ResponseUtil;
|
||||
import com.qiaoba.module.tenant.entity.SysTenant;
|
||||
import com.qiaoba.module.tenant.service.SysTenantService;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 动态切换不同租户的数据源
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023-04-25 22:48:43
|
||||
*/
|
||||
@Component
|
||||
@Order(-10000)
|
||||
public class DynamicDataSourceFilter extends OncePerRequestFilter {
|
||||
|
||||
@Resource
|
||||
private SysTenantService sysTenantService;
|
||||
@Resource
|
||||
private DynamicDataSourceConfig dynamicDataSourceConfig;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
String tenantId = request.getHeader(TenantConstant.HEADER_KEY_TENANT);
|
||||
// 主库或没有tenantId
|
||||
if (StrUtil.isBlank(tenantId)
|
||||
|| TenantConstant.DEFAULT_TENANT_ID.equals(tenantId)
|
||||
|| request.getRequestURI().startsWith("/tenant")) {
|
||||
dynamicDataSourceConfig.setDefaultSetting();
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
SysTenant sysTenant = sysTenantService.selectById(tenantId);
|
||||
if (checkTenantIsNotAllow(response, sysTenant)) {
|
||||
return;
|
||||
}
|
||||
before(sysTenant);
|
||||
filterChain.doFilter(request, response);
|
||||
after();
|
||||
}
|
||||
|
||||
private void before(SysTenant sysTenant) {
|
||||
BaseContext.setTenantId(sysTenant.getTenantId());
|
||||
BaseContext.setSchema(sysTenant.getMode().equals(SysTenant.SCHEMA_MODE));
|
||||
// 数据源模式-设置第三方数据源
|
||||
if (sysTenant.getMode().equals(SysTenant.DATASOURCE_MODE)) {
|
||||
//设置当前租户对应的数据源
|
||||
BaseContext.setDataSource(DynamicDatasourceConstant.MASTER_PREFIX + sysTenant.getTenantId());
|
||||
}
|
||||
// 字段模式/Schema模式-数据源选择默认数据源
|
||||
else {
|
||||
BaseContext.setDataSource(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void after() {
|
||||
BaseContext.clearAllHolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查租户是否不允许访问
|
||||
*
|
||||
* @param sysTenant sysTenant
|
||||
* @return 是->不允许
|
||||
*/
|
||||
private boolean checkTenantIsNotAllow(HttpServletResponse response, SysTenant sysTenant) throws IOException {
|
||||
if (Objects.isNull(sysTenant)) {
|
||||
// 未找到租户信息
|
||||
ResponseUtil.errorAuth(response, 401, "未找到租户信息");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sysTenant.getStatus().equals(BaseEnum.ABNORMAL.getCode())) {
|
||||
// 封禁状态
|
||||
ResponseUtil.errorAuth(response, 401, "租户已被封禁");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DateUtil.compare(sysTenant.getExpireTime(), new Date()) < 0) {
|
||||
// 已过期
|
||||
ResponseUtil.errorAuth(response, 401, "租户已过期");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -48,7 +48,9 @@ public class MysqlDataHandler implements DataHandler {
|
||||
// 手动提交
|
||||
conn.setAutoCommit(false);
|
||||
// 创建表
|
||||
initTables(conn);
|
||||
if (needCreateTables) {
|
||||
initTables(conn);
|
||||
}
|
||||
// 处理 sys_config
|
||||
handleSysConfig(conn, tenantId);
|
||||
// 处理 sys_post
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.qiaoba.module.tenant.service;
|
||||
|
||||
import com.qiaoba.module.tenant.entity.SysTenantDatasource;
|
||||
import com.qiaoba.module.tenant.entity.param.SysTenantDatasourceParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -52,4 +53,12 @@ public interface SysTenantDatasourceService {
|
||||
* @return list
|
||||
*/
|
||||
List<SysTenantDatasource> selectList(String tenantId);
|
||||
|
||||
/**
|
||||
* 查询租户数据源
|
||||
*
|
||||
* @param param 条件
|
||||
* @return list
|
||||
*/
|
||||
List<SysTenantDatasource> selectList(SysTenantDatasourceParam param);
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
package com.qiaoba.module.tenant.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.qiaoba.common.base.enums.BaseEnum;
|
||||
import com.qiaoba.common.base.enums.DataBaseEnum;
|
||||
import com.qiaoba.common.database.entity.DynamicDataSource;
|
||||
import com.qiaoba.common.database.service.DynamicDatasourceService;
|
||||
import com.qiaoba.module.tenant.entity.SysTenantDatasource;
|
||||
import com.qiaoba.module.tenant.entity.param.SysTenantDatasourceParam;
|
||||
import com.qiaoba.module.tenant.service.SysTenantDatasourceService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 动态数据源接口
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/6/9 13:16
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DynamicDatasourceServiceImpl implements DynamicDatasourceService {
|
||||
|
||||
private final SysTenantDatasourceService sysTenantDatasourceService;
|
||||
|
||||
@Override
|
||||
public List<DynamicDataSource> loadAllTenantDatasource() {
|
||||
SysTenantDatasourceParam param = new SysTenantDatasourceParam();
|
||||
param.setIsUse(BaseEnum.YES.getCode());
|
||||
List<SysTenantDatasource> datasourceList = sysTenantDatasourceService.selectList(param);
|
||||
return transform(datasourceList);
|
||||
}
|
||||
|
||||
private List<DynamicDataSource> transform(List<SysTenantDatasource> datasourceList) {
|
||||
List<DynamicDataSource> dynamicDataSourceList = new ArrayList<>();
|
||||
for (SysTenantDatasource datasource : datasourceList) {
|
||||
DynamicDataSource dynamicDataSource = BeanUtil.copyProperties(datasource, DynamicDataSource.class);
|
||||
dynamicDataSource.setDriver(DataBaseEnum.getDriver(datasource.getType()));
|
||||
dynamicDataSource.setUrl(DataBaseEnum.getUrl(datasource.getType(), datasource.getIp(), datasource.getPort(), datasource.getName()));
|
||||
dynamicDataSourceList.add(dynamicDataSource);
|
||||
}
|
||||
return dynamicDataSourceList;
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
package com.qiaoba.module.tenant.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.qiaoba.common.base.enums.BaseEnum;
|
||||
import com.qiaoba.module.tenant.entity.SysTenantDatasource;
|
||||
import com.qiaoba.module.tenant.entity.param.SysTenantDatasourceParam;
|
||||
import com.qiaoba.module.tenant.mapper.SysTenantDatasourceMapper;
|
||||
import com.qiaoba.module.tenant.service.SysTenantDatasourceService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -25,11 +27,7 @@ public class SysTenantDatasourceServiceImpl implements SysTenantDatasourceServic
|
||||
|
||||
@Override
|
||||
public SysTenantDatasource selectMaster(String tenantId) {
|
||||
QueryWrapper<SysTenantDatasource> wrapper = new QueryWrapper<>();
|
||||
wrapper.lambda()
|
||||
.eq(SysTenantDatasource::getTenantId, tenantId)
|
||||
.eq(SysTenantDatasource::getIsMaster, BaseEnum.YES.getCode());
|
||||
return sysTenantDatasourceMapper.selectOne(wrapper);
|
||||
return sysTenantDatasourceMapper.selectOne(paramToWrapper(new SysTenantDatasourceParam(tenantId, BaseEnum.YES.getCode())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -49,9 +47,21 @@ public class SysTenantDatasourceServiceImpl implements SysTenantDatasourceServic
|
||||
|
||||
@Override
|
||||
public List<SysTenantDatasource> selectList(String tenantId) {
|
||||
return sysTenantDatasourceMapper.selectList(paramToWrapper(new SysTenantDatasourceParam(tenantId)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysTenantDatasource> selectList(SysTenantDatasourceParam param) {
|
||||
return sysTenantDatasourceMapper.selectList(paramToWrapper(param));
|
||||
}
|
||||
|
||||
private QueryWrapper<SysTenantDatasource> paramToWrapper(SysTenantDatasourceParam param) {
|
||||
QueryWrapper<SysTenantDatasource> wrapper = new QueryWrapper<>();
|
||||
wrapper.lambda()
|
||||
.eq(SysTenantDatasource::getTenantId, tenantId);
|
||||
return sysTenantDatasourceMapper.selectList(wrapper);
|
||||
.eq(StrUtil.isNotBlank(param.getTenantId()), SysTenantDatasource::getTenantId, param.getTenantId())
|
||||
.eq(StrUtil.isNotBlank(param.getIsUse()), SysTenantDatasource::getIsUse, param.getIsUse())
|
||||
.eq(StrUtil.isNotBlank(param.getIsMaster()), SysTenantDatasource::getIsMaster, param.getIsMaster());
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package com.qiaoba.module.tenant.service.impl;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.qiaoba.auth.utils.SecurityUtil;
|
||||
import com.qiaoba.common.base.DatasourceService;
|
||||
import com.qiaoba.common.base.constants.BaseConstant;
|
||||
import com.qiaoba.common.base.enums.BaseEnum;
|
||||
import com.qiaoba.common.base.enums.DataBaseEnum;
|
||||
import com.qiaoba.common.base.exceptions.ServiceException;
|
||||
@ -38,7 +38,7 @@ import java.util.Objects;
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysTenantServiceImpl implements SysTenantService, DatasourceService {
|
||||
public class SysTenantServiceImpl implements SysTenantService {
|
||||
|
||||
@Value("${qiaoba.datasource.master.driver}")
|
||||
private String driver;
|
||||
@ -143,8 +143,8 @@ public class SysTenantServiceImpl implements SysTenantService, DatasourceService
|
||||
if (SysTenant.COLUMN_MODE.equals(sysTenant.getMode())) {
|
||||
return column();
|
||||
}
|
||||
if (SysTenant.DATABASE_MODE.equals(sysTenant.getMode())) {
|
||||
return database(sysTenant.getTenantId());
|
||||
if (SysTenant.SCHEMA_MODE.equals(sysTenant.getMode())) {
|
||||
return schema(sysTenant.getTenantId());
|
||||
}
|
||||
if (SysTenant.DATASOURCE_MODE.equals(sysTenant.getMode())) {
|
||||
return datasource(sysTenant.getTenantId());
|
||||
@ -163,8 +163,8 @@ public class SysTenantServiceImpl implements SysTenantService, DatasourceService
|
||||
/**
|
||||
* 处理数据库模式
|
||||
*/
|
||||
private Connection database(String tenantId) {
|
||||
String realUrl = this.url.replaceFirst(baseDatabase, baseDatabase + "-" + tenantId);
|
||||
private Connection schema(String tenantId) {
|
||||
String realUrl = this.url.replaceFirst(baseDatabase, baseDatabase + BaseConstant.HYPHEN_JOIN_STR + tenantId);
|
||||
return JdbcUtil.getConnection(driver, realUrl, username, password);
|
||||
}
|
||||
|
||||
@ -179,13 +179,4 @@ public class SysTenantServiceImpl implements SysTenantService, DatasourceService
|
||||
return JdbcUtil.getConnection(DataBaseEnum.getDriver(master.getType()), DataBaseEnum.getUrl(master.getType(), master.getIp(), master.getPort(), master.getName()), master.getUsername(), master.getPassword());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTenantInfo(String tenantId) {
|
||||
SysTenant sysTenant = selectById(tenantId);
|
||||
if (Objects.isNull(sysTenant)) {
|
||||
return false;
|
||||
}
|
||||
// todo 检查租户有没有过期/禁用
|
||||
return sysTenant.getStatus().equals(BaseEnum.NORMAL.getCode());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user