From 0a01ca8497ac85f78c3c1e42f9cb2bf0bb91875b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=85=BE?= <3467447354@qq.com> Date: Sat, 21 Sep 2024 11:52:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../muyu/auth/service/SysLoginService.java | 1 + .../core/constant/SecurityConstants.java | 2 + .../common/core/constant/TokenConstants.java | 5 + .../core/exception/ServiceException.java | 2 +- cloud-common/cloud-common-saas/pom.xml | 33 +++++++ .../many/datasource/ManyDataSource.java | 98 +++++++++++++++++++ .../constents/DatasourceContent.java | 19 ++++ .../domain/model/DataSourceInfo.java | 50 ++++++++++ .../factory/DruidDataSourceFactory.java | 40 ++++++++ .../holder/DynamicDataSourceHolder.java | 42 ++++++++ .../datasource/role/DynamicDataSource.java | 55 +++++++++++ .../common/saas/contents/SaaSConstant.java | 12 +++ .../common/saas/domain/model/EntInfo.java | 25 +++++ .../common/saas/exception/SaaSException.java | 28 ++++++ .../saas/interceptor/SaaSInterceptor.java | 49 ++++++++++ .../saas/interceptor/WebMvcSaaSConfig.java | 31 ++++++ ...ot.autoconfigure.AutoConfiguration.imports | 3 + .../common/security/service/TokenService.java | 3 +- .../muyu/common/system/domain/SysFirm.java | 5 + .../muyu/common/system/domain/SysUser.java | 5 + .../system/remote/RemoteUserService.java | 5 + .../factory/RemoteUserFallbackFactory.java | 7 ++ cloud-common/pom.xml | 1 + cloud-modules/cloud-modules-gen/pom.xml | 5 - cloud-modules/cloud-modules-system/pom.xml | 5 +- .../muyu/system/CloudSystemApplication.java | 1 + .../system/controller/SysUserController.java | 6 ++ .../com/muyu/system/mapper/SysUserMapper.java | 3 + .../muyu/system/service/SysUserService.java | 3 + .../service/impl/SysUserServiceImpl.java | 5 + .../resources/mapper/system/SysUserMapper.xml | 3 + cloud-modules/cloud-test/pom.xml | 76 ++++++++++++++ .../java/com/muyu/test/TestApplication.java | 22 +++++ .../muyu/test/controller/UserController.java | 32 ++++++ .../main/java/com/muyu/test/domain/User.java | 28 ++++++ .../java/com/muyu/test/mapper/UserMapper.java | 16 +++ .../com/muyu/test/service/UserService.java | 14 +++ .../test/service/impl/UserServiceImpl.java | 21 ++++ cloud-modules/pom.xml | 1 + 39 files changed, 751 insertions(+), 11 deletions(-) create mode 100644 cloud-common/cloud-common-saas/pom.xml create mode 100644 cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/ManyDataSource.java create mode 100644 cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/constents/DatasourceContent.java create mode 100644 cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/domain/model/DataSourceInfo.java create mode 100644 cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/factory/DruidDataSourceFactory.java create mode 100644 cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/holder/DynamicDataSourceHolder.java create mode 100644 cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/role/DynamicDataSource.java create mode 100644 cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/contents/SaaSConstant.java create mode 100644 cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/domain/model/EntInfo.java create mode 100644 cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/exception/SaaSException.java create mode 100644 cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/interceptor/SaaSInterceptor.java create mode 100644 cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/interceptor/WebMvcSaaSConfig.java create mode 100644 cloud-common/cloud-common-saas/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 cloud-modules/cloud-test/pom.xml create mode 100644 cloud-modules/cloud-test/src/main/java/com/muyu/test/TestApplication.java create mode 100644 cloud-modules/cloud-test/src/main/java/com/muyu/test/controller/UserController.java create mode 100644 cloud-modules/cloud-test/src/main/java/com/muyu/test/domain/User.java create mode 100644 cloud-modules/cloud-test/src/main/java/com/muyu/test/mapper/UserMapper.java create mode 100644 cloud-modules/cloud-test/src/main/java/com/muyu/test/service/UserService.java create mode 100644 cloud-modules/cloud-test/src/main/java/com/muyu/test/service/impl/UserServiceImpl.java diff --git a/cloud-auth/src/main/java/com/muyu/auth/service/SysLoginService.java b/cloud-auth/src/main/java/com/muyu/auth/service/SysLoginService.java index ff0af1a..ad14e53 100644 --- a/cloud-auth/src/main/java/com/muyu/auth/service/SysLoginService.java +++ b/cloud-auth/src/main/java/com/muyu/auth/service/SysLoginService.java @@ -123,5 +123,6 @@ public class SysLoginService { throw new ServiceException(registerResult.getMsg()); } recordLogService.recordLogininfor(username, Constants.REGISTER, "注册成功"); + } } diff --git a/cloud-common/cloud-common-core/src/main/java/com/muyu/common/core/constant/SecurityConstants.java b/cloud-common/cloud-common-core/src/main/java/com/muyu/common/core/constant/SecurityConstants.java index d326727..5fbd20a 100644 --- a/cloud-common/cloud-common-core/src/main/java/com/muyu/common/core/constant/SecurityConstants.java +++ b/cloud-common/cloud-common-core/src/main/java/com/muyu/common/core/constant/SecurityConstants.java @@ -50,4 +50,6 @@ public class SecurityConstants { * 角色权限 */ public static final String ROLE_PERMISSION = "role_permission"; + + public static final String SAAS_KEY = "ent_code"; } diff --git a/cloud-common/cloud-common-core/src/main/java/com/muyu/common/core/constant/TokenConstants.java b/cloud-common/cloud-common-core/src/main/java/com/muyu/common/core/constant/TokenConstants.java index 38abd57..b1de420 100644 --- a/cloud-common/cloud-common-core/src/main/java/com/muyu/common/core/constant/TokenConstants.java +++ b/cloud-common/cloud-common-core/src/main/java/com/muyu/common/core/constant/TokenConstants.java @@ -21,4 +21,9 @@ public class TokenConstants { */ public final static String SECRET = "abcdefghijklmnsalieopadfaqawefwerstuvwxyz"; + /** + * token + */ + private static final String TOKEN = "token"; + } diff --git a/cloud-common/cloud-common-core/src/main/java/com/muyu/common/core/exception/ServiceException.java b/cloud-common/cloud-common-core/src/main/java/com/muyu/common/core/exception/ServiceException.java index 5039bc0..11bb283 100644 --- a/cloud-common/cloud-common-core/src/main/java/com/muyu/common/core/exception/ServiceException.java +++ b/cloud-common/cloud-common-core/src/main/java/com/muyu/common/core/exception/ServiceException.java @@ -5,7 +5,7 @@ package com.muyu.common.core.exception; * * @author muyu */ -public final class ServiceException extends RuntimeException { +public class ServiceException extends RuntimeException { private static final long serialVersionUID = 1L; /** diff --git a/cloud-common/cloud-common-saas/pom.xml b/cloud-common/cloud-common-saas/pom.xml new file mode 100644 index 0000000..ed99b7f --- /dev/null +++ b/cloud-common/cloud-common-saas/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + com.muyu + cloud-common + 3.6.3 + + + cloud-common-saas + + + 17 + 17 + UTF-8 + + + + + + + com.muyu + cloud-common-security + + + + com.muyu + cloud-common-datasource + + + diff --git a/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/ManyDataSource.java b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/ManyDataSource.java new file mode 100644 index 0000000..9f28b73 --- /dev/null +++ b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/ManyDataSource.java @@ -0,0 +1,98 @@ +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.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.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @Author: DongZeLiang + * @date: 2024/6/3 + * @Description: 多数据源 + * @Version: 1.0 + */ +@Log4j2 +@Component +@AutoConfiguration(before = MybatisPlusAutoConfiguration.class) +public class ManyDataSource implements ApplicationRunner{ + + + private List dataSourceInfoList(){ + RemoteUserService remoteUserService = SpringUtils.getBean(RemoteUserService.class); + Result> tableDataInfoResult = remoteUserService.companyList(); + if (tableDataInfoResult==null){ + throw new SaaSException("saas远调数据源错误"); + } + List data = tableDataInfoResult.getData(); + if (tableDataInfoResult.getCode() ==Result.SUCCESS && data !=null){ + List list = new ArrayList<>(); + for (SysUser row : data) { + list.add( + EntInfo.builder() + .entCode(row.getDatabaseName()) + .ip(DatasourceContent.IP) + .port(DatasourceContent.PORT) + .build() + ); + } + return list; + }else { + log.error("远调数据源错误,远调数据为:{}", JSON.toJSONString(data)); + return null; + } + } + + @Bean + public DynamicDataSource dynamicDataSource(DruidDataSourceFactory druidDataSourceFactory) { + // 企业列表 企业CODE,端口,IP + Map 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; + } + + @Override + public void run(ApplicationArguments args) { + DruidDataSourceFactory druidDataSourceFactory = SpringUtils.getBean(DruidDataSourceFactory.class); + DynamicDataSource dynamicDataSource = SpringUtils.getBean(DynamicDataSource.class); + for (EntInfo entInfo : dataSourceInfoList()) { + DataSourceInfo dataSourceInfo = DataSourceInfo.hostAndPortBuild( + entInfo.getEntCode(), entInfo.getIp(), entInfo.getPort() + ); + DruidDataSource druidDataSource = druidDataSourceFactory.create(dataSourceInfo); + dynamicDataSource.put(dataSourceInfo.getKey(), druidDataSource); + log.info("存储数据连接池为:key:{}",dataSourceInfo.getKey()); + } + } + +} diff --git a/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/constents/DatasourceContent.java b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/constents/DatasourceContent.java new file mode 100644 index 0000000..a740466 --- /dev/null +++ b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/constents/DatasourceContent.java @@ -0,0 +1,19 @@ +package com.muyu.cloud.common.many.datasource.constents; + +/** + * @author DongZl + * @description: 数据源常量 + * @Date 2023-8-1 上午 11:02 + */ +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 = "159.75.188.178"; + + public final static Integer PORT = 3306; +} diff --git a/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/domain/model/DataSourceInfo.java b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/domain/model/DataSourceInfo.java new file mode 100644 index 0000000..73cc26e --- /dev/null +++ b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/domain/model/DataSourceInfo.java @@ -0,0 +1,50 @@ +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 lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author DongZl + * @description: 数据源实体类 + * @Date 2023-8-1 上午 11:15 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DataSourceInfo { + + /** + * 键 + */ + private String key; + + /** + * 地址 + */ + private String url; + + /** + * 用户名 + */ + private String userName; + + /** + * 密码 + */ + private String password; + + + public static DataSourceInfo hostAndPortBuild(String key, String host, Integer port) { + return DataSourceInfo.builder() + .key(key) + .url(StringUtils.format(DatasourceContent.DATASOURCE_URL, host, port, key)) + .password(DatasourceContent.PASSWORD) + .userName(DatasourceContent.USER_NAME) + .build(); + } +} diff --git a/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/factory/DruidDataSourceFactory.java b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/factory/DruidDataSourceFactory.java new file mode 100644 index 0000000..7ceb782 --- /dev/null +++ b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/factory/DruidDataSourceFactory.java @@ -0,0 +1,40 @@ +package com.muyu.cloud.common.many.datasource.factory; + +import com.alibaba.druid.pool.DruidDataSource; +import com.muyu.cloud.common.many.datasource.domain.model.DataSourceInfo; +import lombok.extern.log4j.Log4j2; +import org.springframework.stereotype.Component; + +import java.sql.SQLException; + +/** + * @Author: DongZeLiang + * @date: 2024/6/3 + * @Description: Druid工厂 + * @Version: 1.0 + */ +@Log4j2 +@Component +public class DruidDataSourceFactory { + + /** + * @Description: 根据传递的数据源信息测试数据库连接 + * @Author Dongzl + */ + public DruidDataSource create(DataSourceInfo dataSourceInfo) { + DruidDataSource druidDataSource = new DruidDataSource(); + druidDataSource.setUrl(dataSourceInfo.getUrl()); + druidDataSource.setUsername(dataSourceInfo.getUserName()); + druidDataSource.setPassword(dataSourceInfo.getPassword()); + druidDataSource.setBreakAfterAcquireFailure(true); + druidDataSource.setConnectionErrorRetryAttempts(0); + try { + druidDataSource.getConnection(2000); + log.info("{} -> 数据源连接成功", dataSourceInfo.getKey()); + return druidDataSource; + } catch (SQLException throwables) { + log.error("数据源 {} 连接失败,用户名:{},密码 {}",dataSourceInfo.getUrl(),dataSourceInfo.getUserName(),dataSourceInfo.getPassword()); + return null; + } + } +} diff --git a/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/holder/DynamicDataSourceHolder.java b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/holder/DynamicDataSourceHolder.java new file mode 100644 index 0000000..e53229a --- /dev/null +++ b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/holder/DynamicDataSourceHolder.java @@ -0,0 +1,42 @@ +package com.muyu.cloud.common.many.datasource.holder; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.Assert; + +/** + * 数据源切换处理 + * + * @author Dongzl + */ +@Slf4j +public class DynamicDataSourceHolder { + /** + * 保存动态数据源名称 + */ + private static final ThreadLocal DYNAMIC_DATASOURCE_KEY = new ThreadLocal<>(); + + /** + * 设置/切换数据源,决定当前线程使用哪个数据源 + */ + public static void setDynamicDataSourceKey(String key){ + log.info("数据源切换为:{}",key); + DYNAMIC_DATASOURCE_KEY.set(key); + } + + /** + * 获取动态数据源名称,默认使用mater数据源 + */ + public static String getDynamicDataSourceKey(){ + String key = DYNAMIC_DATASOURCE_KEY.get(); + Assert.notNull(key, "请携带数据标识"); + return key; + } + + /** + * 移除当前数据源 + */ + public static void removeDynamicDataSourceKey(){ + log.info("移除数据源:{}",DYNAMIC_DATASOURCE_KEY.get()); + DYNAMIC_DATASOURCE_KEY.remove(); + } +} diff --git a/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/role/DynamicDataSource.java b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/role/DynamicDataSource.java new file mode 100644 index 0000000..b6996ab --- /dev/null +++ b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/many/datasource/role/DynamicDataSource.java @@ -0,0 +1,55 @@ +package com.muyu.cloud.common.many.datasource.role; + +import com.alibaba.druid.pool.DruidDataSource; +import com.muyu.cloud.common.many.datasource.holder.DynamicDataSourceHolder; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +import java.util.Map; + +/** + * 动态数据源 + * 调用AddDefineDataSource组件的addDefineDynamicDataSource()方法,获取原来targetdatasources的map,并将新的数据源信息添加到map中,并替换targetdatasources中的map + * 切换数据源时可以使用@DataSource(value = "数据源名称"),或者DynamicDataSourceContextHolder.setContextKey("数据源名称") + * @author Dongzl + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +public class DynamicDataSource extends AbstractRoutingDataSource { + /** + * 备份所有数据源信息 + */ + private Map defineTargetDataSources; + + /** + * + * @param key 键 + * @return 存在结果 true存在 false不存在 + */ + public boolean hashKey(String key){ + return defineTargetDataSources.containsKey(key); + } + + /** + * 添加数据库 + * @param key 键 + * @param value 数据源 + */ + public void put(String key, DruidDataSource value) { + defineTargetDataSources.put(key, value); + this.afterPropertiesSet(); + } + + /** + * 决定当前线程使用哪个数据源 + */ + @Override + protected Object determineCurrentLookupKey() { + return DynamicDataSourceHolder.getDynamicDataSourceKey(); + } +} diff --git a/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/contents/SaaSConstant.java b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/contents/SaaSConstant.java new file mode 100644 index 0000000..241ce32 --- /dev/null +++ b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/contents/SaaSConstant.java @@ -0,0 +1,12 @@ +package com.muyu.cloud.common.saas.contents; + +/** + * @Author: DongZeLiang + * @date: 2024/6/3 + * @Description: SAAS常量 + * @Version: 1.0 + */ +public class SaaSConstant { + + public final static String SAAS_KEY = "ent-code"; +} diff --git a/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/domain/model/EntInfo.java b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/domain/model/EntInfo.java new file mode 100644 index 0000000..5c1985a --- /dev/null +++ b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/domain/model/EntInfo.java @@ -0,0 +1,25 @@ +package com.muyu.cloud.common.saas.domain.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Author: DongZeLiang + * @date: 2024/6/3 + * @Description: 企业信息 + * @Version: 1.0 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class EntInfo { + + private String entCode; + + private String ip; + + private Integer port; +} diff --git a/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/exception/SaaSException.java b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/exception/SaaSException.java new file mode 100644 index 0000000..b2b4cc7 --- /dev/null +++ b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/exception/SaaSException.java @@ -0,0 +1,28 @@ +package com.muyu.cloud.common.saas.exception; + + +import com.muyu.common.core.exception.ServiceException; + +/** + * @Author: DongZeLiang + * @date: 2024/6/3 + * @Description: SaaS异常类 + * @Version: 1.0 + */ +public class SaaSException extends ServiceException { + + public SaaSException (String message, Integer code) { + super(message, code); + } + + public SaaSException (String message) { + super(message); + } + + /** + * 空构造方法,避免反序列化问题 + */ + public SaaSException () { + super(); + } +} diff --git a/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/interceptor/SaaSInterceptor.java b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/interceptor/SaaSInterceptor.java new file mode 100644 index 0000000..d7b3891 --- /dev/null +++ b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/interceptor/SaaSInterceptor.java @@ -0,0 +1,49 @@ +package com.muyu.cloud.common.saas.interceptor; + +import com.muyu.cloud.common.many.datasource.holder.DynamicDataSourceHolder; +import com.muyu.cloud.common.many.datasource.role.DynamicDataSource; +import com.muyu.cloud.common.saas.contents.SaaSConstant; +import com.muyu.cloud.common.saas.exception.SaaSException; +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 lombok.extern.log4j.Log4j2; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.AsyncHandlerInterceptor; + + +@Log4j2 +public class SaaSInterceptor implements AsyncHandlerInterceptor { + + /** + * 之前 + */ + @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); + log.info("SaaS拦截器拦截到请求,设置数据源为:{}", SaaSKey); + return true; + } + + /** + * 之后 + */ + @Override + public void afterConcurrentHandlingStarted (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + DynamicDataSourceHolder.removeDynamicDataSourceKey(); + } +} diff --git a/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/interceptor/WebMvcSaaSConfig.java b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/interceptor/WebMvcSaaSConfig.java new file mode 100644 index 0000000..4c79417 --- /dev/null +++ b/cloud-common/cloud-common-saas/src/main/java/com/muyu/cloud/common/saas/interceptor/WebMvcSaaSConfig.java @@ -0,0 +1,31 @@ +package com.muyu.cloud.common.saas.interceptor; + +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 拦截器配置 + * + * @author muyu + */ +public class WebMvcSaaSConfig implements WebMvcConfigurer { + /** + * 不需要拦截的地址 + */ + public static final String[] excludeUrls = {"/login", "/logout", "/refresh"}; + + @Override + public void addInterceptors (InterceptorRegistry registry) { + registry.addInterceptor(getHeaderInterceptor()) + .addPathPatterns("/**") + .excludePathPatterns(excludeUrls) + .order(-10); + } + + /** + * 自定义请求头拦截器 + */ + public SaaSInterceptor getHeaderInterceptor () { + return new SaaSInterceptor(); + } +} diff --git a/cloud-common/cloud-common-saas/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/cloud-common/cloud-common-saas/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..70148cf --- /dev/null +++ b/cloud-common/cloud-common-saas/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,3 @@ +com.muyu.cloud.common.saas.interceptor.WebMvcSaaSConfig +com.muyu.cloud.common.many.datasource.ManyDataSource +com.muyu.cloud.common.many.datasource.factory.DruidDataSourceFactory diff --git a/cloud-common/cloud-common-security/src/main/java/com/muyu/common/security/service/TokenService.java b/cloud-common/cloud-common-security/src/main/java/com/muyu/common/security/service/TokenService.java index 454e87c..9dd8488 100644 --- a/cloud-common/cloud-common-security/src/main/java/com/muyu/common/security/service/TokenService.java +++ b/cloud-common/cloud-common-security/src/main/java/com/muyu/common/security/service/TokenService.java @@ -44,7 +44,6 @@ public class TokenService { String token = IdUtils.fastUUID(); Long userId = loginUser.getSysUser().getUserId(); String userName = loginUser.getSysUser().getUserName(); - Integer firmId = loginUser.getSysUser().getFirmId(); loginUser.setToken(token); loginUser.setUserid(userId); loginUser.setUsername(userName); @@ -56,7 +55,7 @@ public class TokenService { claimsMap.put(SecurityConstants.USER_KEY, token); claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId); claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName); - claimsMap.put(SecurityConstants.DETAILS_FIRM_ID,firmId); + claimsMap.put(SecurityConstants.SAAS_KEY,loginUser.getSysUser().getDatabaseName()); // 接口返回信息 Map rspMap = new HashMap(); diff --git a/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/domain/SysFirm.java b/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/domain/SysFirm.java index f404f20..2607952 100644 --- a/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/domain/SysFirm.java +++ b/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/domain/SysFirm.java @@ -92,6 +92,11 @@ public class SysFirm extends BaseEntity { */ private String firmDesc; + /** + * 所属数据库 + */ + private String databaseName; + /** *启用状态(1.开业 2.停业 3.休业) */ diff --git a/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/domain/SysUser.java b/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/domain/SysUser.java index 169f74a..7633bca 100644 --- a/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/domain/SysUser.java +++ b/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/domain/SysUser.java @@ -88,6 +88,11 @@ public class SysUser extends BaseEntity { */ private Integer firmId; + /** + * 所属数据库 + */ + private String databaseName; + /** * 帐号状态(0正常 1停用) */ diff --git a/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/remote/RemoteUserService.java b/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/remote/RemoteUserService.java index cb968e0..1730fb9 100644 --- a/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/remote/RemoteUserService.java +++ b/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/remote/RemoteUserService.java @@ -9,6 +9,8 @@ import com.muyu.common.system.domain.LoginUser; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; +import java.util.List; + /** * 用户服务 * @@ -37,4 +39,7 @@ public interface RemoteUserService { */ @PostMapping("/user/register") public Result registerUserInfo (@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + + @GetMapping("/user/companyList") + public Result> companyList (); } diff --git a/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/remote/factory/RemoteUserFallbackFactory.java b/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/remote/factory/RemoteUserFallbackFactory.java index b7f4d60..f7e6600 100644 --- a/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/remote/factory/RemoteUserFallbackFactory.java +++ b/cloud-common/cloud-common-system/src/main/java/com/muyu/common/system/remote/factory/RemoteUserFallbackFactory.java @@ -9,6 +9,8 @@ import org.slf4j.LoggerFactory; import org.springframework.cloud.openfeign.FallbackFactory; import org.springframework.stereotype.Component; +import java.util.List; + /** * 用户服务降级处理 * @@ -31,6 +33,11 @@ public class RemoteUserFallbackFactory implements FallbackFactory registerUserInfo (SysUser sysUser, String source) { return Result.error("注册用户失败:" + throwable.getMessage()); } + + @Override + public Result> companyList() { + return Result.error("发现用户失败:" + throwable.getMessage()); + } }; } } diff --git a/cloud-common/pom.xml b/cloud-common/pom.xml index d00dfc6..a7a40be 100644 --- a/cloud-common/pom.xml +++ b/cloud-common/pom.xml @@ -20,6 +20,7 @@ cloud-common-system cloud-common-xxl cloud-common-rabbit + cloud-common-saas cloud-common diff --git a/cloud-modules/cloud-modules-gen/pom.xml b/cloud-modules/cloud-modules-gen/pom.xml index c5de3a6..1b38a27 100644 --- a/cloud-modules/cloud-modules-gen/pom.xml +++ b/cloud-modules/cloud-modules-gen/pom.xml @@ -65,11 +65,6 @@ cloud-common-api-doc - - - com.muyu - cloud-common-xxl - diff --git a/cloud-modules/cloud-modules-system/pom.xml b/cloud-modules/cloud-modules-system/pom.xml index 4116679..dd7a85a 100644 --- a/cloud-modules/cloud-modules-system/pom.xml +++ b/cloud-modules/cloud-modules-system/pom.xml @@ -71,15 +71,14 @@ cloud-common-api-doc - com.muyu - cloud-common-xxl + cloud-common-rabbit com.muyu - cloud-common-rabbit + cloud-common-core diff --git a/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/CloudSystemApplication.java b/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/CloudSystemApplication.java index b01e5db..52d36ce 100644 --- a/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/CloudSystemApplication.java +++ b/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/CloudSystemApplication.java @@ -2,6 +2,7 @@ package com.muyu.system; import com.muyu.common.security.annotation.EnableCustomConfig; import com.muyu.common.security.annotation.EnableMyFeignClients; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/controller/SysUserController.java b/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/controller/SysUserController.java index bc0b5fe..6a4ab17 100644 --- a/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/controller/SysUserController.java +++ b/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/controller/SysUserController.java @@ -114,6 +114,12 @@ public class SysUserController extends BaseController { return Result.success(sysUserVo); } + @GetMapping("/companyList") + public Result> list(){ + List list = userService.companyList(); + return Result.success(list); + } + /** * 注册用户信息 */ diff --git a/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/mapper/SysUserMapper.java b/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/mapper/SysUserMapper.java index e037b34..fa92973 100644 --- a/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/mapper/SysUserMapper.java +++ b/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/mapper/SysUserMapper.java @@ -139,4 +139,7 @@ public interface SysUserMapper extends BaseMapper { * @return 结果 */ public SysUser checkEmailUnique (String email); + + List companyList(); + } diff --git a/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/service/SysUserService.java b/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/service/SysUserService.java index f4c6167..fdaffa7 100644 --- a/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/service/SysUserService.java +++ b/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/service/SysUserService.java @@ -225,4 +225,7 @@ public interface SysUserService extends IService { * @return 结果 */ public String importUser (List userList, Boolean isUpdateSupport, String operName); + + List companyList(); + } diff --git a/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/service/impl/SysUserServiceImpl.java b/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/service/impl/SysUserServiceImpl.java index c1d3f18..7e17f2c 100644 --- a/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/service/impl/SysUserServiceImpl.java +++ b/cloud-modules/cloud-modules-system/src/main/java/com/muyu/system/service/impl/SysUserServiceImpl.java @@ -500,4 +500,9 @@ public class SysUserServiceImpl extends ServiceImpl impl return successMsg.toString(); } + @Override + public List companyList() { + return userMapper.companyList(); + } + } diff --git a/cloud-modules/cloud-modules-system/src/main/resources/mapper/system/SysUserMapper.xml b/cloud-modules/cloud-modules-system/src/main/resources/mapper/system/SysUserMapper.xml index 6f633b7..e78cd4c 100644 --- a/cloud-modules/cloud-modules-system/src/main/resources/mapper/system/SysUserMapper.xml +++ b/cloud-modules/cloud-modules-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -183,6 +183,9 @@ and del_flag = '0' limit 1 + insert into sys_user( diff --git a/cloud-modules/cloud-test/pom.xml b/cloud-modules/cloud-test/pom.xml new file mode 100644 index 0000000..f0418c2 --- /dev/null +++ b/cloud-modules/cloud-test/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + + com.muyu + cloud-modules + 3.6.3 + + + cloud-test + + + 17 + 17 + UTF-8 + + + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + com.mysql + mysql-connector-j + + + + + com.muyu + cloud-common-datasource + + + + + com.muyu + cloud-common-datascope + + + + + com.muyu + cloud-common-log + + + + + com.muyu + cloud-common-api-doc + + + diff --git a/cloud-modules/cloud-test/src/main/java/com/muyu/test/TestApplication.java b/cloud-modules/cloud-test/src/main/java/com/muyu/test/TestApplication.java new file mode 100644 index 0000000..fbd6752 --- /dev/null +++ b/cloud-modules/cloud-test/src/main/java/com/muyu/test/TestApplication.java @@ -0,0 +1,22 @@ +package com.muyu.test; + +import com.muyu.common.security.annotation.EnableMyFeignClients; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @Author:张腾 + * @Package:com.muyu.test + * @Project:cloud-server-8 + * @name:TestApplication + * @Date:2024/9/20 19:16 + */ +@SpringBootApplication +@EnableMyFeignClients +public class TestApplication { + + public static void main(String[] args) { + SpringApplication.run(TestApplication.class,args); + } +} diff --git a/cloud-modules/cloud-test/src/main/java/com/muyu/test/controller/UserController.java b/cloud-modules/cloud-test/src/main/java/com/muyu/test/controller/UserController.java new file mode 100644 index 0000000..8486e2c --- /dev/null +++ b/cloud-modules/cloud-test/src/main/java/com/muyu/test/controller/UserController.java @@ -0,0 +1,32 @@ +package com.muyu.test.controller; + +import com.muyu.common.core.domain.Result; +import com.muyu.test.domain.User; +import com.muyu.test.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @Author:张腾 + * @Package:com.muyu.test.controller + * @Project:cloud-server-8 + * @name:UserController + * @Date:2024/9/20 19:14 + */ +@RestController("/admin") +public class UserController { + + @Autowired + private UserService userService; + + @GetMapping("/selectAll") + public Result> selectAll(){ + List list = userService.list(); + list.forEach(System.out::println); + return Result.success(list); + } + +} diff --git a/cloud-modules/cloud-test/src/main/java/com/muyu/test/domain/User.java b/cloud-modules/cloud-test/src/main/java/com/muyu/test/domain/User.java new file mode 100644 index 0000000..723ce88 --- /dev/null +++ b/cloud-modules/cloud-test/src/main/java/com/muyu/test/domain/User.java @@ -0,0 +1,28 @@ +package com.muyu.test.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Author:张腾 + * @Package:com.muyu.test.domain + * @Project:cloud-server-8 + * @name:User + * @Date:2024/9/20 19:11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName(value = "user",autoResultMap = true) +public class User { + + @TableId(value = "user_id") + private Integer userId; + + private String userName; +} diff --git a/cloud-modules/cloud-test/src/main/java/com/muyu/test/mapper/UserMapper.java b/cloud-modules/cloud-test/src/main/java/com/muyu/test/mapper/UserMapper.java new file mode 100644 index 0000000..04d55ec --- /dev/null +++ b/cloud-modules/cloud-test/src/main/java/com/muyu/test/mapper/UserMapper.java @@ -0,0 +1,16 @@ +package com.muyu.test.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.muyu.test.domain.User; +import org.apache.ibatis.annotations.Mapper; + +/** + * @Author:张腾 + * @Package:com.muyu.test.mapper + * @Project:cloud-server-8 + * @name:UserMapper + * @Date:2024/9/20 19:13 + */ +@Mapper +public interface UserMapper extends BaseMapper { +} diff --git a/cloud-modules/cloud-test/src/main/java/com/muyu/test/service/UserService.java b/cloud-modules/cloud-test/src/main/java/com/muyu/test/service/UserService.java new file mode 100644 index 0000000..c717ced --- /dev/null +++ b/cloud-modules/cloud-test/src/main/java/com/muyu/test/service/UserService.java @@ -0,0 +1,14 @@ +package com.muyu.test.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.muyu.test.domain.User; + +/** + * @Author:张腾 + * @Package:com.muyu.test.service + * @Project:cloud-server-8 + * @name:UserService + * @Date:2024/9/20 19:13 + */ +public interface UserService extends IService { +} diff --git a/cloud-modules/cloud-test/src/main/java/com/muyu/test/service/impl/UserServiceImpl.java b/cloud-modules/cloud-test/src/main/java/com/muyu/test/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..44c0d83 --- /dev/null +++ b/cloud-modules/cloud-test/src/main/java/com/muyu/test/service/impl/UserServiceImpl.java @@ -0,0 +1,21 @@ +package com.muyu.test.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.muyu.test.domain.User; +import com.muyu.test.mapper.UserMapper; +import com.muyu.test.service.UserService; +import org.springframework.stereotype.Service; + +/** + * @Author:张腾 + * @Package:com.muyu.test.service.impl + * @Project:cloud-server-8 + * @name:UserServiceImpl + * @Date:2024/9/20 19:14 + */ +@Service +public class UserServiceImpl + extends ServiceImpl implements UserService { + + +} diff --git a/cloud-modules/pom.xml b/cloud-modules/pom.xml index ba0d555..40b5df8 100644 --- a/cloud-modules/pom.xml +++ b/cloud-modules/pom.xml @@ -12,6 +12,7 @@ cloud-modules-system cloud-modules-gen cloud-modules-file + cloud-test cloud-modules