fix(): 修复sass公共配置
parent
124cae3bb3
commit
368bcda83d
|
@ -10,7 +10,6 @@
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>cloud-common-saas</artifactId>
|
<artifactId>cloud-common-saas</artifactId>
|
||||||
<description>SaaS公共依赖</description>
|
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
@ -25,10 +24,11 @@
|
||||||
<artifactId>cloud-common-datasource</artifactId>
|
<artifactId>cloud-common-datasource</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 权限依赖 -->
|
<!-- 鉴权依赖 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.muyu</groupId>
|
<groupId>com.muyu</groupId>
|
||||||
<artifactId>cloud-common-security</artifactId>
|
<artifactId>cloud-common-security</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,127 @@
|
||||||
|
package com.muyu.cloud.common.many.datasource;
|
||||||
|
|
||||||
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
||||||
|
import com.muyu.cloud.common.many.datasource.constents.DatasourceContent;
|
||||||
|
import com.muyu.cloud.common.many.datasource.domain.model.DataSourceInfo;
|
||||||
|
import com.muyu.cloud.common.many.datasource.factory.DruidDataSourceFactory;
|
||||||
|
import com.muyu.cloud.common.many.datasource.role.DynamicDataSource;
|
||||||
|
import com.muyu.cloud.common.saas.domain.model.EntInfo;
|
||||||
|
import com.muyu.cloud.common.saas.exception.SaaSException;
|
||||||
|
import com.muyu.common.core.domain.Result;
|
||||||
|
import com.muyu.common.core.utils.SpringUtils;
|
||||||
|
import com.muyu.common.system.domain.SysUser;
|
||||||
|
import com.muyu.common.system.remote.RemoteUserService;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.apache.ibatis.session.SqlSessionFactory;
|
||||||
|
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: zi run
|
||||||
|
* @Date 2024/9/20 14:52
|
||||||
|
* @Description 多数据源
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
@Component
|
||||||
|
@AutoConfiguration(before = MybatisPlusAutoConfiguration.class)
|
||||||
|
public class ManyDataSource implements ApplicationRunner {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在应用启动时执行,初始化数据源连接池。
|
||||||
|
* 获取 DruidDataSourceFactory 和 DynamicDataSource 实例,
|
||||||
|
* 遍历数据源信息列表,为每个数据源创建 Druid 数据源并存储到动态数据源中。
|
||||||
|
* @param args 应用启动参数
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments args) {
|
||||||
|
DruidDataSourceFactory druidDataSourceFactory = SpringUtils.getBean(DruidDataSourceFactory.class);
|
||||||
|
DynamicDataSource dynamicDataSource = SpringUtils.getBean(DynamicDataSource.class);
|
||||||
|
dataSourceInfoList().stream()
|
||||||
|
.map(entInfo -> DataSourceInfo.hostAndPortBuild(
|
||||||
|
entInfo.getEntCode(), entInfo.getIp(), entInfo.getPort()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.forEach(dataSourceInfo -> {
|
||||||
|
DruidDataSource druidDataSource = druidDataSourceFactory.create(dataSourceInfo);
|
||||||
|
dynamicDataSource.put(dataSourceInfo.getKey(), druidDataSource);
|
||||||
|
log.info("存储数据连接池为:key:{}",dataSourceInfo.getKey());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据源信息
|
||||||
|
* @return 企业信息
|
||||||
|
*/
|
||||||
|
private List<EntInfo> dataSourceInfoList(){
|
||||||
|
RemoteUserService remoteUserService = SpringUtils.getBean(RemoteUserService.class);
|
||||||
|
Result<List<SysUser>> entListResult = remoteUserService.entList();
|
||||||
|
if (entListResult==null){
|
||||||
|
throw new SaaSException("saas远调数据源错误");
|
||||||
|
}
|
||||||
|
List<SysUser> data = entListResult.getData();
|
||||||
|
if (entListResult.getCode() == Result.SUCCESS && data != null){
|
||||||
|
return data.stream()
|
||||||
|
.map(d -> EntInfo.builder()
|
||||||
|
.entCode(d.getDatabaseName())
|
||||||
|
.ip(DatasourceContent.IP)
|
||||||
|
.port(DatasourceContent.PORT)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
}else {
|
||||||
|
log.error("远调数据源错误,远调数据为:{}", JSON.toJSONString(data));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建一个 DynamicDataSource Bean,配置多个数据源。
|
||||||
|
* 从数据源信息列表中获取配置,并使用 DruidDataSourceFactory 创建数据源实例。
|
||||||
|
* @param druidDataSourceFactory 创建 Druid 数据源的工厂
|
||||||
|
* @return 配置好的 DynamicDataSource 实例
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public DynamicDataSource dynamicDataSource(DruidDataSourceFactory druidDataSourceFactory) {
|
||||||
|
Map<Object, Object> dataSourceMap = dataSourceInfoList().stream()
|
||||||
|
.map(entInfo -> DataSourceInfo.hostAndPortBuild(
|
||||||
|
entInfo.getEntCode(),
|
||||||
|
entInfo.getIp(),
|
||||||
|
entInfo.getPort()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
dataSourceInfo -> dataSourceInfo.getKey(),
|
||||||
|
dataSourceInfo -> druidDataSourceFactory.create(dataSourceInfo)
|
||||||
|
));
|
||||||
|
|
||||||
|
//设置动态数据源
|
||||||
|
DynamicDataSource dynamicDataSource = new DynamicDataSource();
|
||||||
|
dynamicDataSource.setTargetDataSources(dataSourceMap);
|
||||||
|
dynamicDataSource.setDefineTargetDataSources(dataSourceMap);
|
||||||
|
return dynamicDataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 SqlSessionFactory Bean,用于 MyBatis 数据库操作。
|
||||||
|
* 该方法接收动态数据源并配置 SqlSessionFactory,返回
|
||||||
|
* 用于与数据库交互的 SqlSessionFactory 实例。
|
||||||
|
* @param dataSource 动态数据源
|
||||||
|
* @return 配置好的 SqlSessionFactory 实例
|
||||||
|
* @throws Exception 可能抛出的异常
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public SqlSessionFactory sqlSessionFactory(DynamicDataSource dataSource) throws Exception {
|
||||||
|
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
|
||||||
|
sessionFactory.setDataSource(dataSource);
|
||||||
|
return sessionFactory.getObject();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.muyu.cloud.common.many.datasource.constents;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: zi run
|
||||||
|
* @Date 2024/9/20 14:52
|
||||||
|
* @Description 数据源常量
|
||||||
|
*/
|
||||||
|
public class DatasourceContent {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据源地址
|
||||||
|
*/
|
||||||
|
public final static String URL = "jdbc:mysql://{}:{}/{}?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据源用户名
|
||||||
|
*/
|
||||||
|
public final static String USERNAME = "root";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据源密码
|
||||||
|
*/
|
||||||
|
public final static String PASSWORD = "wx0713101x";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据源IP
|
||||||
|
*/
|
||||||
|
public final static String IP = "127.0.0.1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据源端口号
|
||||||
|
*/
|
||||||
|
public final static Integer PORT = 3307;
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package com.muyu.common.many.datasource.domain.model;
|
package com.muyu.cloud.common.many.datasource.domain.model;
|
||||||
|
|
||||||
|
import com.muyu.cloud.common.many.datasource.constents.DatasourceContent;
|
||||||
import com.muyu.common.core.utils.StringUtils;
|
import com.muyu.common.core.utils.StringUtils;
|
||||||
import com.muyu.common.many.datasource.constents.DatasourceContent;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
@ -9,7 +9,7 @@ import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: zi run
|
* @Author: zi run
|
||||||
* @Date 2024/9/18 22:01
|
* @Date 2024/9/20 14:52
|
||||||
* @Description 数据源实体类
|
* @Description 数据源实体类
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
@ -39,12 +39,12 @@ public class DataSourceInfo {
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
|
|
||||||
public static DataSourceInfo hostAndPortBuild(String key, String host, Integer port){
|
public static DataSourceInfo hostAndPortBuild(String key, String host, Integer port) {
|
||||||
return DataSourceInfo.builder()
|
return DataSourceInfo.builder()
|
||||||
.key(key)
|
.key(key)
|
||||||
.url(StringUtils.format(DatasourceContent.DATASOURCE_URL, host, port))
|
.url(StringUtils.format(DatasourceContent.URL, host, port, key))
|
||||||
.password(DatasourceContent.PASSWORD)
|
.password(DatasourceContent.PASSWORD)
|
||||||
.userName(DatasourceContent.USER_NAME)
|
.userName(DatasourceContent.USERNAME)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package com.muyu.common.many.datasource.factory;
|
package com.muyu.cloud.common.many.datasource.factory;
|
||||||
|
|
||||||
import com.alibaba.druid.pool.DruidDataSource;
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
import com.muyu.common.many.datasource.domain.model.DataSourceInfo;
|
import com.muyu.cloud.common.many.datasource.domain.model.DataSourceInfo;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import java.sql.SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: zi run
|
* @Author: zi run
|
||||||
* @Date 2024/9/18 22:08
|
* @Date 2024/9/20 14:52
|
||||||
* @Description Druid工厂
|
* @Description Druid工厂
|
||||||
*/
|
*/
|
||||||
@Log4j2
|
@Log4j2
|
||||||
|
@ -19,7 +19,7 @@ public class DruidDataSourceFactory {
|
||||||
/**
|
/**
|
||||||
* 根据传递的数据源信息测试数据库连接
|
* 根据传递的数据源信息测试数据库连接
|
||||||
* @param dataSourceInfo 数据源实体类
|
* @param dataSourceInfo 数据源实体类
|
||||||
* @return
|
* @return Druid连接池数据源
|
||||||
*/
|
*/
|
||||||
public DruidDataSource create(DataSourceInfo dataSourceInfo) {
|
public DruidDataSource create(DataSourceInfo dataSourceInfo) {
|
||||||
DruidDataSource druidDataSource = new DruidDataSource();
|
DruidDataSource druidDataSource = new DruidDataSource();
|
||||||
|
@ -32,7 +32,7 @@ public class DruidDataSourceFactory {
|
||||||
druidDataSource.getConnection(2000);
|
druidDataSource.getConnection(2000);
|
||||||
log.info("{} -> 数据源连接成功", dataSourceInfo.getKey());
|
log.info("{} -> 数据源连接成功", dataSourceInfo.getKey());
|
||||||
return druidDataSource;
|
return druidDataSource;
|
||||||
} catch (SQLException sqlException) {
|
} catch (SQLException e) {
|
||||||
log.error("数据源 {} 连接失败,用户名:{},密码 {}",dataSourceInfo.getUrl(),dataSourceInfo.getUserName(),dataSourceInfo.getPassword());
|
log.error("数据源 {} 连接失败,用户名:{},密码 {}",dataSourceInfo.getUrl(),dataSourceInfo.getUserName(),dataSourceInfo.getPassword());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package com.muyu.common.many.datasource.holder;
|
package com.muyu.cloud.common.many.datasource.holder;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: zi run
|
* @Author: zi run
|
||||||
* @Date 2024/9/18 22:08
|
* @Date 2024/9/20 14:52
|
||||||
* @Description 数据源切换处理
|
* @Description 数据源切换处理
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
|
@ -1,26 +1,25 @@
|
||||||
package com.muyu.common.many.datasource.role;
|
package com.muyu.cloud.common.many.datasource.role;
|
||||||
|
|
||||||
import com.alibaba.druid.pool.DruidDataSource;
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
import com.muyu.common.many.datasource.holder.DynamicDataSourceHolder;
|
import com.muyu.cloud.common.many.datasource.holder.DynamicDataSourceHolder;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.*;
|
||||||
import lombok.Data;
|
import lombok.experimental.SuperBuilder;
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
|
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: zi run
|
* @Author: zi run
|
||||||
* @Date 2024/9/18 22:14
|
* @Date 2024/9/20 14:56
|
||||||
* @Description 动态数据源 调用AddDefineDataSource组件的addDefineDynamicDataSource()方法,
|
* @Description 动态数据源
|
||||||
* 获取原来targetdatasources的map,并将新的数据源信息添加到map中,并替换targetdatasources中的map切换数据源时可以使用
|
* 调用AddDefineDataSource组件的addDefineDynamicDataSource()方法,获取原来targetdatasources的map,
|
||||||
* @DataSource(value = "数据源名称"),或者DynamicDataSourceContextHolder.setContextKey("数据源名称")
|
* 并将新的数据源信息添加到map中,并替换targetdatasources中的map
|
||||||
|
* 切换数据源时可以使用@DataSource(value = "数据源名称"),或者DynamicDataSourceContextHolder.setContextKey("数据源名称")
|
||||||
*/
|
*/
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class DynamicDataSource extends AbstractRoutingDataSource {
|
public class DynamicDataSource extends AbstractRoutingDataSource {
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.muyu.cloud.common.saas.contents;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: zi run
|
||||||
|
* @Date 2024/9/20 19:40
|
||||||
|
* @Description SAAS常量
|
||||||
|
*/
|
||||||
|
public class SaaSConstant {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SaaS键名
|
||||||
|
*/
|
||||||
|
public final static String SAAS_KEY = "ent-code";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截器白名单
|
||||||
|
*/
|
||||||
|
public static final String[] EXCLUDE_URLS = {"/login", "/logout", "/refresh"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截器执行优先级
|
||||||
|
*/
|
||||||
|
public static final Integer INTERCEPTOR_ORDER = -10;
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.muyu.common.saas.domain.model;
|
package com.muyu.cloud.common.saas.domain.model;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
|
@ -7,7 +7,7 @@ import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: zi run
|
* @Author: zi run
|
||||||
* @Date 2024/9/19 14:24
|
* @Date 2024/9/20 19:41
|
||||||
* @Description 企业信息
|
* @Description 企业信息
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
@ -16,9 +16,18 @@ import lombok.NoArgsConstructor;
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class EntInfo {
|
public class EntInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业编码
|
||||||
|
*/
|
||||||
private String entCode;
|
private String entCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP地址
|
||||||
|
*/
|
||||||
private String ip;
|
private String ip;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 端口号
|
||||||
|
*/
|
||||||
private Integer port;
|
private Integer port;
|
||||||
}
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
package com.muyu.common.saas.exception;
|
package com.muyu.cloud.common.saas.exception;
|
||||||
|
|
||||||
|
|
||||||
import com.muyu.common.core.exception.ServiceException;
|
import com.muyu.common.core.exception.ServiceException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: zi run
|
* @Author: zi run
|
||||||
* @Date 2024/9/18 21:28
|
* @Date 2024/9/20 19:41
|
||||||
* @Description SaaS异常类
|
* @Description SaaS异常类
|
||||||
*/
|
*/
|
||||||
public class SaaSException extends ServiceException {
|
public class SaaSException extends ServiceException {
|
||||||
|
@ -17,6 +18,9 @@ public class SaaSException extends ServiceException {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 空构造方法,避免反序列化问题
|
||||||
|
*/
|
||||||
public SaaSException () {
|
public SaaSException () {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.muyu.cloud.common.saas.interceptor;
|
||||||
|
|
||||||
|
import com.muyu.cloud.common.saas.contents.SaaSConstant;
|
||||||
|
import com.muyu.cloud.common.many.datasource.holder.DynamicDataSourceHolder;
|
||||||
|
import com.muyu.cloud.common.saas.exception.SaaSException;
|
||||||
|
import com.muyu.cloud.common.many.datasource.role.DynamicDataSource;
|
||||||
|
import com.muyu.common.core.utils.ServletUtils;
|
||||||
|
import com.muyu.common.core.utils.SpringUtils;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: zi run
|
||||||
|
* @Date 2024/9/20 19:41
|
||||||
|
* @Description SAAS拦截器
|
||||||
|
*/
|
||||||
|
public class SaaSInterceptor implements AsyncHandlerInterceptor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求执行之前触发
|
||||||
|
* @param request servlet请求对象
|
||||||
|
* @param response servlet响应对象
|
||||||
|
* @param handler 处理器
|
||||||
|
* @return 是否放行
|
||||||
|
* @throws Exception 可能抛出的异常
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
|
if (!(handler instanceof HandlerMethod)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String SaaSKey = ServletUtils.getHeader(request, SaaSConstant.SAAS_KEY);
|
||||||
|
if (SaaSKey == null) {
|
||||||
|
throw new SaaSException("SaaS非法访问");
|
||||||
|
}else {
|
||||||
|
DynamicDataSource dynamicDataSource = SpringUtils.getBean(DynamicDataSource.class);
|
||||||
|
if (!dynamicDataSource.hashKey(SaaSKey)){
|
||||||
|
throw new SaaSException("SaaS非法访问");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DynamicDataSourceHolder.setDynamicDataSourceKey(SaaSKey);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求执行之后触发
|
||||||
|
* @param request servlet请求对象
|
||||||
|
* @param response servlet响应对象
|
||||||
|
* @param handler 处理器
|
||||||
|
* @throws Exception servlet响应对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void afterConcurrentHandlingStarted (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
|
DynamicDataSourceHolder.removeDynamicDataSourceKey();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,33 +1,34 @@
|
||||||
package com.muyu.common.saas.interceptor;
|
package com.muyu.cloud.common.saas.interceptor;
|
||||||
|
|
||||||
import com.muyu.common.saas.constants.SaaSConstant;
|
import com.muyu.cloud.common.saas.contents.SaaSConstant;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: zi run
|
* 拦截器配置
|
||||||
* @Date 2024/9/18 21:07
|
*
|
||||||
* @Description 拦截器配置
|
* @author muyu
|
||||||
*/
|
*/
|
||||||
public class WebMvcSaaSConfig implements WebMvcConfigurer {
|
public class WebMvcSaaSConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加拦截器
|
* 添加请求拦截器配置
|
||||||
* @param registry 注册器
|
* @param registry 拦截器注册表,用于注册自定义拦截器
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors (InterceptorRegistry registry) {
|
||||||
registry.addInterceptor(getHeaderInterceptor())
|
registry.addInterceptor(getHeaderInterceptor())
|
||||||
|
.addPathPatterns("/**")
|
||||||
.excludePathPatterns(SaaSConstant.EXCLUDE_URLS)
|
.excludePathPatterns(SaaSConstant.EXCLUDE_URLS)
|
||||||
.order(SaaSConstant.INTERCEPTOR_ORDER);
|
.order(SaaSConstant.INTERCEPTOR_ORDER);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义请求头拦截器
|
* 自定义请求头拦截器
|
||||||
* @return SAAS拦截器对象
|
* @return SaaS拦截器
|
||||||
*/
|
*/
|
||||||
public SaaSInterceptor getHeaderInterceptor() {
|
public SaaSInterceptor getHeaderInterceptor () {
|
||||||
return new SaaSInterceptor();
|
return new SaaSInterceptor();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,82 +0,0 @@
|
||||||
package com.muyu.common.many.datasource;
|
|
||||||
|
|
||||||
import com.alibaba.druid.pool.DruidDataSource;
|
|
||||||
import com.muyu.common.core.utils.SpringUtils;
|
|
||||||
import com.muyu.common.many.datasource.domain.model.DataSourceInfo;
|
|
||||||
import com.muyu.common.many.datasource.factory.DruidDataSourceFactory;
|
|
||||||
import com.muyu.common.many.datasource.role.DynamicDataSource;
|
|
||||||
import com.muyu.common.saas.domain.model.EntInfo;
|
|
||||||
import lombok.extern.log4j.Log4j2;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Primary;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author: zi run
|
|
||||||
* @Date 2024/9/18 22:08
|
|
||||||
* @Description 多数据源
|
|
||||||
*/
|
|
||||||
@Log4j2
|
|
||||||
@Component
|
|
||||||
public class ManyDataSource {
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void init(){
|
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
Thread.sleep(10000);
|
|
||||||
} catch (InterruptedException ignored) {}
|
|
||||||
DruidDataSourceFactory druidDataSourceFactory = SpringUtils.getBean(DruidDataSourceFactory.class);
|
|
||||||
DynamicDataSource dynamicDataSource = SpringUtils.getBean(DynamicDataSource.class);
|
|
||||||
EntInfo entInfo = EntInfo.builder()
|
|
||||||
.entCode("ent_4588")
|
|
||||||
.ip("192.168.40.132")
|
|
||||||
.port(3308)
|
|
||||||
.build();
|
|
||||||
DataSourceInfo dataSourceInfo = DataSourceInfo.hostAndPortBuild(entInfo.getEntCode(), entInfo.getIp(), entInfo.getPort());
|
|
||||||
DruidDataSource druidDataSource = druidDataSourceFactory.create(dataSourceInfo);
|
|
||||||
dynamicDataSource.put(dataSourceInfo.getKey(), druidDataSource);
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private List<EntInfo> dataSourceInfoList(){
|
|
||||||
List<EntInfo> list = new ArrayList<>();
|
|
||||||
list.add(
|
|
||||||
EntInfo.builder()
|
|
||||||
.entCode("ent_4587")
|
|
||||||
.ip("192.168.40.132")
|
|
||||||
.port(3307)
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@Primary
|
|
||||||
public DynamicDataSource dynamicDataSource(DruidDataSourceFactory druidDataSourceFactory) {
|
|
||||||
|
|
||||||
// 企业列表 企业CODE,端口,IP
|
|
||||||
|
|
||||||
Map<Object, Object> dataSourceMap = new HashMap<>();
|
|
||||||
dataSourceInfoList()
|
|
||||||
.stream()
|
|
||||||
.map(entInfo -> DataSourceInfo.hostAndPortBuild(entInfo.getEntCode(), entInfo.getIp(), entInfo.getPort()))
|
|
||||||
.forEach(dataSourceInfo -> {
|
|
||||||
dataSourceMap.put(dataSourceInfo.getKey(), druidDataSourceFactory.create(dataSourceInfo));
|
|
||||||
});
|
|
||||||
//设置动态数据源
|
|
||||||
DynamicDataSource dynamicDataSource = new DynamicDataSource();
|
|
||||||
// dynamicDataSource.setDefaultTargetDataSource(masterDataSource());
|
|
||||||
dynamicDataSource.setTargetDataSources(dataSourceMap);
|
|
||||||
//将数据源信息备份在defineTargetDataSources中
|
|
||||||
dynamicDataSource.setDefineTargetDataSources(dataSourceMap);
|
|
||||||
return dynamicDataSource;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
package com.muyu.common.many.datasource.constents;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author: zi run
|
|
||||||
* @Date 2024/9/18 22:06
|
|
||||||
* @Description 数据源常量
|
|
||||||
*/
|
|
||||||
public class DatasourceContent {
|
|
||||||
|
|
||||||
public final static String DATASOURCE_URL = "jdbc:mysql://{}:{}/{}?useUnicode=true&" +
|
|
||||||
"characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
|
|
||||||
|
|
||||||
public final static String USER_NAME = "root";
|
|
||||||
|
|
||||||
public final static String PASSWORD = "root";
|
|
||||||
|
|
||||||
public final static String IP = "127.0.0.1";
|
|
||||||
|
|
||||||
public final static Integer PORT = 3307;
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package com.muyu.common.saas.constants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author: zi run
|
|
||||||
* @Date 2024/9/18 21:22
|
|
||||||
* @Description SAAS常量
|
|
||||||
*/
|
|
||||||
public class SaaSConstant {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saas键名
|
|
||||||
*/
|
|
||||||
public static final String SAAS_KEY = "ent-code";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SaaS异常提示
|
|
||||||
*/
|
|
||||||
public static final String SAAS_EXCEPTION_MSG = "SaaS非法访问";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 白名单地址
|
|
||||||
*/
|
|
||||||
public static final String[] EXCLUDE_URLS = {"/login", "/logout", "/refresh"};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拦截器优先级
|
|
||||||
*/
|
|
||||||
public static final Integer INTERCEPTOR_ORDER = 10;
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
package com.muyu.common.saas.interceptor;
|
|
||||||
|
|
||||||
import com.muyu.common.core.utils.ServletUtils;
|
|
||||||
import com.muyu.common.core.utils.SpringUtils;
|
|
||||||
import com.muyu.common.many.datasource.holder.DynamicDataSourceHolder;
|
|
||||||
import com.muyu.common.many.datasource.role.DynamicDataSource;
|
|
||||||
import com.muyu.common.saas.constants.SaaSConstant;
|
|
||||||
import com.muyu.common.saas.exception.SaaSException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import org.springframework.web.method.HandlerMethod;
|
|
||||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author: zi run
|
|
||||||
* @Date 2024/9/18 21:14
|
|
||||||
* @Description SAAS拦截器
|
|
||||||
*/
|
|
||||||
public class SaaSInterceptor implements AsyncHandlerInterceptor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行之前触发
|
|
||||||
* @param request servlet请求
|
|
||||||
* @param response servlet响应
|
|
||||||
* @param handler 处理器
|
|
||||||
* @return 是否放行
|
|
||||||
* @throws Exception 最大异常
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean preHandle(HttpServletRequest request,
|
|
||||||
HttpServletResponse response, Object handler) throws Exception {
|
|
||||||
if(! (handler instanceof HandlerMethod)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
String SaaSKey = ServletUtils.getHeader(request, SaaSConstant.SAAS_KEY);
|
|
||||||
if(SaaSKey == null) {
|
|
||||||
throw new SaaSException(SaaSConstant.SAAS_EXCEPTION_MSG);
|
|
||||||
} else {
|
|
||||||
DynamicDataSource dynamicDataSource = SpringUtils.getBean(DynamicDataSource.class);
|
|
||||||
if (!dynamicDataSource.hashKey(SaaSKey)){
|
|
||||||
throw new SaaSException(SaaSConstant.SAAS_EXCEPTION_MSG);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DynamicDataSourceHolder.setDynamicDataSourceKey(SaaSKey);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行之后触发
|
|
||||||
* @param request servlet请求
|
|
||||||
* @param response servlet响应
|
|
||||||
* @param handler 处理器
|
|
||||||
* @throws Exception 最大异常
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void afterConcurrentHandlingStarted(HttpServletRequest request,
|
|
||||||
HttpServletResponse response, Object handler) throws Exception {
|
|
||||||
DynamicDataSourceHolder.removeDynamicDataSourceKey();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +1,3 @@
|
||||||
com.muyu.common.saas.interceptor.WebMvcSaaSConfig
|
com.muyu.cloud.common.saas.interceptor.WebMvcSaaSConfig
|
||||||
|
com.muyu.cloud.common.many.datasource.ManyDataSource
|
||||||
|
com.muyu.cloud.common.many.datasource.factory.DruidDataSourceFactory
|
||||||
|
|
|
@ -93,6 +93,10 @@ public class SysUser extends BaseEntity {
|
||||||
* 删除标志(0代表存在 2代表删除)
|
* 删除标志(0代表存在 2代表删除)
|
||||||
*/
|
*/
|
||||||
private String delFlag;
|
private String delFlag;
|
||||||
|
/**
|
||||||
|
* 数据库名称
|
||||||
|
*/
|
||||||
|
private String databaseName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 最后登录IP
|
* 最后登录IP
|
||||||
|
|
|
@ -9,6 +9,8 @@ import com.muyu.common.system.domain.LoginUser;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户服务
|
* 用户服务
|
||||||
*
|
*
|
||||||
|
@ -37,4 +39,12 @@ public interface RemoteUserService {
|
||||||
*/
|
*/
|
||||||
@PostMapping("/user/register")
|
@PostMapping("/user/register")
|
||||||
public Result<Boolean> registerUserInfo (@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
|
public Result<Boolean> registerUserInfo (@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取企业信息
|
||||||
|
* @return 用户信息
|
||||||
|
*/
|
||||||
|
@GetMapping("/user/entList")
|
||||||
|
public Result<List<SysUser>> entList();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.cloud.openfeign.FallbackFactory;
|
import org.springframework.cloud.openfeign.FallbackFactory;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户服务降级处理
|
* 用户服务降级处理
|
||||||
*
|
*
|
||||||
|
@ -31,6 +33,11 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
|
||||||
public Result<Boolean> registerUserInfo (SysUser sysUser, String source) {
|
public Result<Boolean> registerUserInfo (SysUser sysUser, String source) {
|
||||||
return Result.error("注册用户失败:" + throwable.getMessage());
|
return Result.error("注册用户失败:" + throwable.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<List<SysUser>> entList() {
|
||||||
|
return Result.error("获取企业信息失败:" + throwable.getMessage());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.muyu.system.controller;
|
package com.muyu.system.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.muyu.common.core.domain.Result;
|
import com.muyu.common.core.domain.Result;
|
||||||
import com.muyu.common.core.utils.StringUtils;
|
import com.muyu.common.core.utils.StringUtils;
|
||||||
import com.muyu.common.core.utils.poi.ExcelUtil;
|
import com.muyu.common.core.utils.poi.ExcelUtil;
|
||||||
|
@ -290,4 +291,13 @@ public class SysUserController extends BaseController {
|
||||||
public Result deptTree (SysDept dept) {
|
public Result deptTree (SysDept dept) {
|
||||||
return success(deptService.selectDeptTreeList(dept));
|
return success(deptService.selectDeptTreeList(dept));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取企业信息
|
||||||
|
* @return 用户信息
|
||||||
|
*/
|
||||||
|
@GetMapping("/entList")
|
||||||
|
public Result<List<SysUser>> entList() {
|
||||||
|
return success(userService.entList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.muyu.system.service;
|
package com.muyu.system.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.muyu.common.core.domain.Result;
|
||||||
import com.muyu.common.system.domain.SysUser;
|
import com.muyu.common.system.domain.SysUser;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -225,4 +226,10 @@ public interface SysUserService extends IService<SysUser> {
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String importUser (List<SysUser> userList, Boolean isUpdateSupport, String operName);
|
public String importUser (List<SysUser> userList, Boolean isUpdateSupport, String operName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业信息
|
||||||
|
* @return 用户信息
|
||||||
|
*/
|
||||||
|
List<SysUser> entList();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package com.muyu.system.service.impl;
|
package com.muyu.system.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.muyu.common.core.constant.UserConstants;
|
import com.muyu.common.core.constant.UserConstants;
|
||||||
|
import com.muyu.common.core.domain.Result;
|
||||||
import com.muyu.common.core.exception.ServiceException;
|
import com.muyu.common.core.exception.ServiceException;
|
||||||
import com.muyu.common.core.utils.SpringUtils;
|
import com.muyu.common.core.utils.SpringUtils;
|
||||||
import com.muyu.common.core.utils.StringUtils;
|
import com.muyu.common.core.utils.StringUtils;
|
||||||
|
@ -500,4 +502,14 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||||
return successMsg.toString();
|
return successMsg.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业信息
|
||||||
|
* @return 用户信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<SysUser> entList() {
|
||||||
|
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.last("where database_name!=''");
|
||||||
|
return this.list(queryWrapper);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
<result property="sex" column="sex"/>
|
<result property="sex" column="sex"/>
|
||||||
<result property="avatar" column="avatar"/>
|
<result property="avatar" column="avatar"/>
|
||||||
<result property="password" column="password"/>
|
<result property="password" column="password"/>
|
||||||
|
<result property="databaseName" column="database_name"/>
|
||||||
<result property="status" column="status"/>
|
<result property="status" column="status"/>
|
||||||
<result property="delFlag" column="del_flag"/>
|
<result property="delFlag" column="del_flag"/>
|
||||||
<result property="loginIp" column="login_ip"/>
|
<result property="loginIp" column="login_ip"/>
|
||||||
|
@ -57,6 +58,7 @@
|
||||||
u.password,
|
u.password,
|
||||||
u.sex,
|
u.sex,
|
||||||
u.status,
|
u.status,
|
||||||
|
u.database_name,
|
||||||
u.del_flag,
|
u.del_flag,
|
||||||
u.login_ip,
|
u.login_ip,
|
||||||
u.login_date,
|
u.login_date,
|
||||||
|
|
Loading…
Reference in New Issue