前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spring Boot 构建多租户系统 实现动态切换数据源

Spring Boot 构建多租户系统 实现动态切换数据源

作者头像
@依然范特西
发布于 2023-01-12 06:28:38
发布于 2023-01-12 06:28:38
5.2K00
代码可运行
举报
文章被收录于专栏:云天的博客云天的博客
运行总次数:0
代码可运行

Spring Boot 构建多租户系统 实现动态切换数据源

概述

SaaS(Software as a Service),多租户系统(一套系统,不同租户数据不同) 它只是一种软件架构,从技术角度来说很好实现。主要是运营下去会比较难。

传统模式下的系统

多租户下的系统架构图

多租户的好处 好升级也好维护, 假设我们开发一个应用程序,并且希望这一套程序销售给N个客户用,传统模式下,我们要为N个客户创建 服务器数据库 并为N个客户部署相同的程序N次。采用多租户了就部署一套

实现多租户

实现方式

主流的方案有三种

  • 方案1:共享数据库 共享数据架构 通过租户id进行区分属于那个租户
  • 方案2:共享数据库 多个租户共享数据库 但一个租户一个Schema
  • 方案3:独立数据库 一个租户一个数据库(采用)

方案3实现

采用方案3需要创建一个单独的数据库存储所有的租户信息,并存储租户的数据库和数据源信息

  1. 难点1:不同租户使用的时候如何进行切换数据库?
  2. 难点2:需要动态添加数据源信息
难点1的解决办法
  1. 可以通过域名的方式来识别租户 我们可以为每一个租户提供一个二级域名,通过二级域名就可以实现区分租户比如 zuhu1.saas.com,zuhu2.saas.com
  2. 可以将租户信息作为请求参数传递给服务端,服务端进行一个识别,如 saas.com?tenantId=tenant1,saas.com?tenantId=tenant2。
  3. 可以在请求头Header 设置租户信息,服务端通过解析Header中获取租户信息。

我采用的是 二级域名+Header设置租户信息

难点2的解决办法

因为 使用的是mybatis-plus框架 官网提供了两个多数据源的框架

多数据源既动态数据源,项目开发逐渐扩大,单个数据源、单一数据源已经无法满足需求项目的支撑需求。

由此延伸了多数据源的扩展,下文提供了两种不同方向的扩展插件。

  • dynamic-datasource 开源文档付费,属于组织参与者小锅盖发起的项目
  • mybatis-mate 企业级付费授权,资料文档免费

我使用的是dynamic-datasource这个框架 文档我入手了

采用的框架

我使用的框架 jeecgboot低代码开发框架 jeecgboot集成了dynamic-datasource框架 数据库 mysql

数据表准备
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
-- 租户表
CREATE TABLE `sys_data_source` (
  `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '租户编码',
  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '租户名称',
  `remark` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
  `db_type` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '数据库类型',
  `db_driver` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '驱动类',
  `db_url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '数据源地址',
  `db_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '数据库名称',
  `db_username` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户名',
  `db_password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '密码',
  `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建日期',
  `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
  `update_time` datetime DEFAULT NULL COMMENT '更新日期',
  `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '所属部门',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uk_sdc_rule_code` (`code`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
代码实现动态添加数据源

jeecgboot有一个多数据管理的页面 我就基于他那个功能修改了一下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
    public Result saveDataSource(SysDataSource sysDataSource) {
        try {
            long count = checkDbCode(sysDataSource.getCode());
            if (count > 0) {
                return Result.error("数据源编码已存在");
            }
            String dbPassword = sysDataSource.getDbPassword();
            if (StringUtils.isNotBlank(dbPassword)) {
                String encrypt = SecurityUtil.jiami(dbPassword);
                sysDataSource.setDbPassword(encrypt);
            }
            boolean result = save(sysDataSource);
            if (result) {
                //动态创建数据源
                addDynamicDataSource(sysDataSource, dbPassword);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.OK("添加成功!");
    }

/**
     * 动态添加数据源 【注册mybatis动态数据源】
     *
     * @param sysDataSource 添加数据源数据对象
     * @param dbPassword    未加密的密码
     */
    private void addDynamicDataSource(SysDataSource sysDataSource, String dbPassword) {
        DataSourceProperty dataSourceProperty = new DataSourceProperty();
        dataSourceProperty.setUrl(sysDataSource.getDbUrl());
        dataSourceProperty.setPassword(dbPassword);
        dataSourceProperty.setDriverClassName(sysDataSource.getDbDriver());
        dataSourceProperty.setUsername(sysDataSource.getDbUsername());
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
        try {
            ds.addDataSource(sysDataSource.getCode(), dataSource);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
动态切换数据源
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DynamicDataSourceContextHolder.push("数据源名称");//动态切换数据源

思路:当请求后端接口的时候 通过web拦截器 拦截一下请求头获取租户编码 进行切换

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//web相关
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Resource
    private TenantDsInterceptor tenantDsInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册租户切换数据源拦截器
        registry.addInterceptor(this.tenantDsInterceptor);
    }
}
----------------------------
/**
 * @author :扫地僧 租户切换拦截器
 * @date :2022-12-28 上午 10:40:36
 * @version: V1.0
 * @slogan: 天下风云出我辈,一入代码岁月催
 * @description:
 **/
@Slf4j
@Component
public class TenantDsInterceptor implements HandlerInterceptor {
    @Autowired
    private ISysDataSourceService sysDataSourceService;

    /**
     * 在请求处理前调用
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String requestURI = request.getRequestURI();
        log.info("经过多数据源Interceptor,当前路径是{}", requestURI);
        String tenantId = request.getHeader("tencode");
        //如果tenantId为空,则使用默认数据源
        if (StringUtils.isNotEmpty(tenantId)){
            log.info("拿到的租户编码{}", tenantId);
            sysDataSourceService.changeDsByTenantId(tenantId);
        }
        return true;
    }

    /**
     * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    /**
     * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //清空当前线程数据源
        DynamicDataSourceContextHolder.clear();
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023年01月11日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
【Ian Goodfellow 五问】GAN、深度学习,如何与谷歌竞争
【新智元导读】Ian Goodfellow 昨天在 Quora 上回答网友提问。新智元摘选排名最高的 5 大问题编译整理。如何与谷歌、Facebook 的深度学习研究项目竞争?GAN 有哪些有趣的发展和应用?深度学习接下来会如何?研究人工智能和机器学习,你推荐哪10本书?下面是 Goodfellow 的回答。 独立学习者或研究人员如何与谷歌,Facebook、OpenAI这样的公司里快节奏的深度学习研究相竞争? Ian Goodfellow:在谷歌大脑,我们实际上经常考虑如何选择项目,确保它们值得做,因为世
新智元
2018/03/27
5100
Ian Goodfellow:生成对抗网络 GAN 就是强化学习(超全资料)
【新智元导读】今天,Ian Goodfellow开展了一场有关生成对抗网络(GAN)的最新AMA问答,从他小时候如何学习编程,如何想出GAN这个idea,到具体的技术和应用,Goodfellow都作出了专业而且诚恳的回答。Goodfellow认为不止是GAN,胶囊网络、强化学习、半监督学习等等方法都很重要,也值得更多人重视。 关于GAN:想法来自酒后与同行的争论 问:有传言说你是在一家小酒馆里想出了GAN的idea,是这样吗? Ian Goodfellow :这是真事,不仅仅是传言。我之前在好几次采访中都讲
新智元
2018/03/21
1.3K0
观点 | Ian Goodfellow:关于GANs的那些不为人知的事儿
AI 科技评论按:近日,「GANs 之父」Ian Goodfellow 做客国外一档「你问我答」(Ask Me Anything)的线上问答节目,提问者可以直接对 Ian Goodfellow 提出任何关于 GANs 的问题,下面 AI 科技评论带大家围观 GANs 背后都有哪些不为人知的故事。 以下是 AMA 节目中,Ian Goodfellow 与线上提问者的问答实录,AI 科技评论做了不改动原意的编译。 Gfred:有传言说你是在一家酒吧想出 GAN 的。你能回忆并描述一下当时的情景吗? Ian
AI科技评论
2018/03/29
9500
【干货】Google GAN之父Ian Goodfellow ICCV2017演讲:解读生成对抗网络的原理与应用
【导读】当地时间 10月 22 日到10月29日,两年一度的计算机视觉国际顶级会议 International Conference on Computer Vision(ICCV 2017)在意大利威尼斯开幕。Google Brain 研究科学家 Ian Goodfellow 在会上作为主题为《生成对抗网络(Generative Adversarial Networks)》的Tutorial 最新演讲, 介绍了GAN的原理和最新的应用。为此,专知内容组整理了的Goodfellow的slides,进行了解读
WZEARW
2018/04/09
1.5K0
【干货】Google GAN之父Ian Goodfellow ICCV2017演讲:解读生成对抗网络的原理与应用
Ian Goodfellow谈GANs论文评审:有这些迹象的论文要怀疑
AI 科技评论按:谷歌大脑研究员、「GANs」之父、《Deep Learning》课本作者之一的 Ian Goodfellow 自上次的线上直播里回答了网友们提出的种种问题之后,昨天也在 Twitter 上发表了很多关于 GANs 论文评审、GANs 研究现状的想法。作为一直以来投入了大量精力在 GANs 上的研究者,以及作为参与了许多论文评审的审稿人, Ian Goodfellow 自然为 GANs 的进步感到开心,但他现在也同样对领域内的现状有诸多忧虑。AI 科技评论把相关内容整理如下。 「越是好论
AI科技评论
2018/03/29
4940
Ian Goodfellow谈GANs论文评审:有这些迹象的论文要怀疑
【专知荟萃11】GAN生成式对抗网络知识资料全集(理论/报告/教程/综述/代码等)
生成对抗网络(GAN)专知荟萃 一、理论学习 二、报告 三、教程 四、综述 五、中文博客资料 六、Github资源以及模型 七、最新研究论文 一、理论学习 训练GANs的技巧 参考链接:[http://papers.nips.cc/paper/6124-improved-techniques-for-training-gans.pdf] Energy-Based GANs 以及Yann Le Cun 的相关研究 参考链接:[http://papers.nips.cc/paper/4824-imagenet
WZEARW
2018/04/10
1.1K0
【GAN货】生成对抗网络知识资料全集(论文/代码/教程/视频/文章等)
【导读】当地时间 10月 22 日到10月29日,两年一度的计算机视觉国际顶级会议 International Conference on Computer Vision(ICCV 2017)在意大利威尼斯开幕。Google Brain 研究科学家 Ian Goodfellow 在会上作为主题为《生成对抗网络(Generative Adversarial Networks)》的Tutorial 最新演讲, 介绍了GAN的原理和最新的应用。昨天我们介绍了此内容,请查看 【干货】Google GAN之父Ian
WZEARW
2018/04/09
1.6K0
【新手必备】GAN生成对抗网络论文阅读路线图(附论文下载链接)
作者:İdil Sülo, Middle East Technical University
新智元
2018/12/06
9430
大咖 | GAN之父Ian Goodfellow在Quora:机器学习十问十答
大数据文摘作品,转载要求见文末 编译 | Aileen,张礼俊 笪洁琼,钱天培 近日,GAN之父Ian Goodfellow在Quora上举行了一年一度的live问答活动。不同于去年的独挑大梁,他今年还叫来了他在Google Brain的好基友Alexey Kurakin。本次互动吸引了将近2万Quora用户的参与,两人总共回答了网友提出的35个机器学习相关的问题。 大数据文摘从中精选出10个问题,从机器学习入门到深入探讨都有涉及,带你了解大佬眼中的机器学习。当然,我们也摘录了Ian Goodfellow
大数据文摘
2018/05/25
4842
生成对抗网络(GANs )诞生以来的主要技术进展
关键字全网搜索最新排名 【机器学习算法】:排名第一 【机器学习】:排名第二 【Python】:排名第三 【算法】:排名第四 来源:雷锋网 两年前,蒙特利尔大学 Ian Goodfellow 等学者提出“生成对抗网络”(Generative Adversarial Networks,GANs)的概念,并逐渐引起 AI 业内人士的注意。其实,直到 2015 年,生成对抗网络还称不上是炙手可热。但自今年以来,学界、业界对 GANs 的兴趣出现“井喷”: 多篇重磅论文陆续发表; Facebook、Open AI 等
昱良
2018/04/08
7800
生成对抗网络(GANs )诞生以来的主要技术进展
时下火热的wGAN将变革深度学习?这得从源头讲起
随着柯洁与AlphaGo结束以后,大家是不是对人工智能的底层奥秘越来越有兴趣? 深度学习已经在图像分类、检测等诸多领域取得了突破性的成绩。但是它也存在一些问题。 首先,它与传统的机器学习方法一样,通常假设训练数据与测试数据服从同样的分布,或者是在训练数据上的预测结果与在测试数据上的预测结果服从同样的分布,而实际上这两者存在一定的偏差。另一个问题是深度学习的模型(比如卷积神经网络)有时候并不能很好地学到训练数据中的一些特征。深度对抗学习(deep adversarial learning)就是为了解决上
AI科技大本营
2018/04/27
7400
时下火热的wGAN将变革深度学习?这得从源头讲起
观点 | 争议、流派,有关GAN的一切:Ian Goodfellow Q&A
选自fermatslibrary 机器之心编译 参与:思源、李泽南 自 2014 年提出以来,生成对抗网络(GAN)已经成为深度学习领域里最为重要的方向之一。其无监督学习的特性有助于解决按文本生成图像、提高图片分辨率、药物匹配、检索特定模式的图片等多种任务。近日,GAN 的提出者,谷歌大脑研究科学家 Ian Goodfellow 在问答平台上面向所有人进行了 Q&A 活动,向我们解答了有关 GAN 的背景、技术、流派,以及一些有趣的问题,我们对本次活动的内容进行了整理。 Gfred:有传言说你是在一家酒吧里
机器之心
2018/05/08
9200
观点 | 争议、流派,有关GAN的一切:Ian Goodfellow Q&A
动态 | 2017年里,哪十篇 arXiv 机器学习论文在 Twitter 上最热门?
AI 科技评论按:随着 2017 年结束、2018 年开始,各个媒体和研究者都撰写了各自的年度总结和新年祝愿。在过去一年的论文动态里,除了研究者们在总结文里根据自己的研究兴趣选出论文回顾之外,我们也想看看论文在社交网络上的传播情况,看看广大「群众」都对哪些论文感兴趣。 Twitter 上有个帐号@StatMLPapers 会每天摘录20篇左右机器学习相关论文分别发推,2017年一年共发送了五千多条论文推特。我们找出了其中点赞最多的10条论文推特,给大家看看是哪10篇论文在twitter上得到了最多的关注。
AI科技评论
2018/03/14
9540
动态 | 2017年里,哪十篇 arXiv 机器学习论文在 Twitter 上最热门?
资料 | 生成对抗网络(GAN)论文阅读路线图【打包下载】
为了帮助其他想要了解更多关于GAN技术的人,我想按照我阅读的顺序分享一些我读过的文章。在阅读这些论文之前,如果您不熟悉这些论文,我建议您学习一些深度学习的基础知识。 我也相信其中一些论文背后的数学可能非常困难,所以如果你觉得不舒服,你可以跳过这些部分。
昱良
2018/12/06
5010
资源 | 生成对抗网络及其变体的论文汇总
选自Deephunt 作者:Avinash Hindupur 参与:黄小天、蒋思源 生成对抗网络(GAN)是近段时间以来最受研究者关注的机器学习方法之一,深度学习泰斗 Yann LeCun 就曾多次谈到 这种机器学习理念的巨大价值和未来前景。而各类 GAN 的变体也层出不穷,近日机器之心也报道过生成对抗网络的最新进展与论文集,而本文更注重于从 GAN 及其变体的角度对其论文做一个完整的梳理。 项目地址:https://deephunt.in/the-gan-zoo-79597dc8c347 每一周都会有关于
机器之心
2018/05/07
1.1K0
开发 | 自Ian Goodfellow之后,GANs还有哪些开拓性进展?
AI科技评论按:本文由作者Adit Deshpande总结,AI科技评论编译整理。Adit Deshpande目前是UCLA计算机科学专业生物信息学方向的大二学生。他热衷于将自己的机器学习和计算机视觉
AI科技评论
2018/03/12
7890
开发 | 自Ian Goodfellow之后,GANs还有哪些开拓性进展?
AI与深度学习重点回顾:Denny Britz眼中的2017
【导读】近日,博客WILDML的作者Denny Britz把他眼中的2017年AI和深度学习的大事进行了一番梳理和总结:从AlphaGo的自主学习到AlphaGo Zero的强化学习、进化算法的东山再
WZEARW
2018/04/12
8440
AI与深度学习重点回顾:Denny Britz眼中的2017
Ian Goodfellow:深度学习的8个未来方向
陈桦 编译自 Quora 量子位 报道 | 公众号 QbitAI 深度学习的下一步是什么? 最近,这个问题在美国问答网站Quora上发出没几天,就收到了Ian Goodfellow的回答。 Goodfellow是Google Brain研究员,Deep Learning教科书的第一作者,还曾经在OpenAI工作过一段时间。他最广为人知的成就,是提出了生成对抗网络(GAN)。 以下是他回答的主要内容: 深度学习未来的发展方向很广,以下是其中一些方向: 更优秀的强化学习,以及深度学习和强化学习之间的整合。能更
量子位
2018/03/28
6120
Ian Goodfellow:深度学习的8个未来方向
资源 | 生成对抗网络新进展与论文全集
选自GitHub 参与:蒋思源、吴攀 生成对抗网络(GAN)是近段时间以来最受研究者关注的机器学习方法之一,深度学习泰斗 Yann LeCun 就曾多次谈到 这种机器学习理念的巨大价值和未来前景。在本文中,机器之心总结了 GitHub 上两篇关于 GAN 的资源,其中一篇介绍了 GAN 的一些引人关注的新理论和实践(如 Wasserstein GAN),另一篇则集中展示了大量 GAN 相关的论文。 以下是两篇原文的链接: GAN 理论&实践的新进展:https://casmls.github.io/gene
机器之心
2018/05/07
7850
资源 | 生成对抗网络新进展与论文全集
风靡全球的GANs:一文看尽这“混世魔王”的“三生三世”
也许您已经了解到,当前的人工智能已经可以生成类似于人类的语音,或者生成难以与真实照片区分开的人物图像,甚至达到足以“以假乱真”(假作真时真亦假,无为有处有还无)的地步!
新智元
2020/02/11
5510
推荐阅读
【Ian Goodfellow 五问】GAN、深度学习,如何与谷歌竞争
5100
Ian Goodfellow:生成对抗网络 GAN 就是强化学习(超全资料)
1.3K0
观点 | Ian Goodfellow:关于GANs的那些不为人知的事儿
9500
【干货】Google GAN之父Ian Goodfellow ICCV2017演讲:解读生成对抗网络的原理与应用
1.5K0
Ian Goodfellow谈GANs论文评审:有这些迹象的论文要怀疑
4940
【专知荟萃11】GAN生成式对抗网络知识资料全集(理论/报告/教程/综述/代码等)
1.1K0
【GAN货】生成对抗网络知识资料全集(论文/代码/教程/视频/文章等)
1.6K0
【新手必备】GAN生成对抗网络论文阅读路线图(附论文下载链接)
9430
大咖 | GAN之父Ian Goodfellow在Quora:机器学习十问十答
4842
生成对抗网络(GANs )诞生以来的主要技术进展
7800
时下火热的wGAN将变革深度学习?这得从源头讲起
7400
观点 | 争议、流派,有关GAN的一切:Ian Goodfellow Q&A
9200
动态 | 2017年里,哪十篇 arXiv 机器学习论文在 Twitter 上最热门?
9540
资料 | 生成对抗网络(GAN)论文阅读路线图【打包下载】
5010
资源 | 生成对抗网络及其变体的论文汇总
1.1K0
开发 | 自Ian Goodfellow之后,GANs还有哪些开拓性进展?
7890
AI与深度学习重点回顾:Denny Britz眼中的2017
8440
Ian Goodfellow:深度学习的8个未来方向
6120
资源 | 生成对抗网络新进展与论文全集
7850
风靡全球的GANs:一文看尽这“混世魔王”的“三生三世”
5510
相关推荐
【Ian Goodfellow 五问】GAN、深度学习,如何与谷歌竞争
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档