首页 > 作文

Springboot动态切换数据源的具体实现与原理分析

更新时间:2023-04-04 02:29:56 阅读: 评论:0

目录
前言具体实现:原理分析:总结

前言

在springboot项目中只需一句代码即可实现多个数据源之间的切换:

// 切换sqlrver数据源:datasourcecontextholder.tdatabatype(datasourceenum.sqlrver_datasource);......// 切换mysql数据源    datasourcecontextholder.tdatabatype(datasourceenum.mysql_datasource);

具体实现:

本实例基于springboot2.5+版本实现。

1.配置数据源:

在配置文件中配置多个数据源的连接信息,用不同的前缀作为区别:

# sqlrver数据源1:前缀为:spring.datasource.sqlrverspring.datasource.sqlrver.driver-class-name=com.microsoft.sqlrver.jdbc.sqlrverdriverspring.datasource.sqlrver.jdbc-url=jdbc:sqlrver://localhost:1433;databaname=testspring.datasource.sqlrver.urname=saspring.datasource.sqlrver.password=sa# mysql数据源1:前缀为:spring.datasource.mysqlspring.datasource.mysql.driver-class-name=com.mysql.jdbc.driverspring.datasource.mysql.jdbc-url=jdbc:mysql://localhost:3306/test?uunicode=true&characterencodi蒋勋细说红楼梦160集ng=utf-8&ussl=fal&allowmultiqueries=truespring.datasource.mysql.urname=rootspring.datasource.mysql.password=root# sqllite数据源1:前缀为:spring.datasource.sqlitespring.datasource.sqlite.driver-class-name=org.sqlite.jdbcspring.datasource.sqlite.jdbc-url=jdbc:sqlite:d://sqllite//test.dbspring.datasource.sqlite.urname=spring.datasource.sqlite.password=# sqlrver数据源2:前缀为:spring.datasource.sqlrver2spring.datasource.sqlrver2.driver-class-name=com.microsoft.sqlrver.jdbc.sqlrverdriverspring.datasource.sq现实感情扎心语录lrver2.jdbc-url=jdbc:sqlrver://localhost;databaname=test1spring.datasource.sqlrver2.urname=saspring.datasource.sqlrver2.password=sa# 配置数据库连接池信息spring.datasource.hikari.maximum-pool-size=32spring.datasource.hikari.minimum-idle=16

2.新建枚举类datasourceenum,有几个数据源对应设置几个枚举类。

public enum datasourceenum {    mysql_datasource,    sqlrver_datasource,    sqlrver2_datasource,    sqllite_datasource}

3.新建数据库切换工具类datasourcecontextholder,这里通过threadlocal类型的变量来存储当前数据源枚举类,同时能够保证线程安全。

public class datasourcecontextholder {    /**     * 通过threadlocal保证线程安全     */    private static final threadlocal<datasourceenum> contextholder = new threadlocal<>();    /**     * 设置数据源变量     * @param datasourceenum 数据源变量     */    public static void tdatabatype(datasourceenum datasourceenum) {        system.out.println("修改数据源为:" + datasourceenum);        contextholder.t(datasourceenum);    }    /**     * 获取数据源变量     * @return 数据源变量     */    public static datasourceenum getdatabatype() {        datasourceenum datasourceenum = contextholder.get() == null ? datasourceenum.mysql_datasource : contextholder.get();        system.out.println("当前数据源的类型为:" + datasourceenum);        return datasourceenum;    }    /**     * 清空数据类型     */    public static void cleardatabatype() {        contextholder.remove();    }

4.新建dynamicdatasource类继承abstractroutingdatasource类,并实现determinecurrentlookupkey方法,该方法是指定当前默认数据源的方法。

public class dynamicdatasource extends abstractroutingdatasource {    @override    protected object determinecurrentlookupkey() {        return datasourcecontextholder.getdatabatype();    }}

这个类看似内容不多,但其实继承了abstractroutingdatasource类是实现动态切换数据源的关键。

5.新建datasourceconfig类用来创建bean的实例,其中包括各数据源的datasource实例,dynamicdatasource实例以及跟mybatis相关的sqlssionfactory或spring的jdbctemplate实例。

@configurationpublic class datasourceconfig {    @bean(name = "sqlrverdatasource")    @configurationproperties(prefix = "spring.datasource.sqlrver")    public datasource getdatesource1() {        return datasourcebuilder.create().build();    }    @bean(name = "sqlrver2datasource")    @configurationproperties(prefix = "spring.datasource.sqlrver2")    public datasource getdatesource11() {        return datasourcebuilder.create().build();    }    @bean(name = "mysqldatasource")    @configurationproperties(prefix = "spring.datasource.mysql")    public datasource getdatesource2() {        return datasourcebuilder.create().build();    }    @bean(name = "sqllitedatasource")    @configurationproperties(prefix = "spring.datasource.sqlite")    public datasource getdatesource3() {        return datasourcebuilder.create().build();    }    @bean(name = "dynamicdatasource")    public dynamicdatasource datasource(@qualifier("sqlrverdatasource") datas备课组工作计划ource sqlrverdatasource,                                        @qualifier("sqlrver2datasource") datasource sqlrver2datasource,                                        @qualifier("mysqldatasource") datasource mysqldatasource,                                        @qualifier("sqllitedatasource") datasource sqllitedatasource) {        //配置多数排除的近义词据源        map<object, object> targetdatasource = new hashmap<>();        targetdatasource.put(datasourceenum.sqlrver_datasource, sqlrverdatasource);        targetdatasource.put(datasourceenum.mysql_datasource, mysqldatasource);        targetdatasource.put(datasourceenum.sqllite_datasource, sqllitedatasource);        targetdatasource.put(datasourceenum.sqlrver2_datasource, sqlrver2datasource);        dynamicdatasource datasource = new dynamicdatasource();        //多数据源        datasource.ttargetdatasources(targetdatasource);        //默认数据源        datasource.tdefaulttargetdatasource(sqlrverdatasource);        return datasource;    }    @bean(name = "sqlssionfactory")    public sqlssionfactory test1sqlssionfactory(@qualifier("dynamicdatasource") datasource dynamicdatasource)            throws exception {        sqlssionfactorybean bean = new sqlssionfactorybean();        bean.tdatasource(dynamicdatasource);        return bean.getobject();    }    @bean(name = "jdbctemplate")    public jdbctemplate test1jdbctemplate(@qualifier("dynamicdatasource") datasource dynamicdatasource) {        return new jdbctemplate(dynamicdatasource);    }}

这样就把我们切换数据库锁需要的bean全部交给spring容器中了,使用时直接通过datasourcecontextholder.tdatabatype(datasourceenum datasourceenum);这个方法指定数据源对应的枚举类即可。

原理分析:

其实我们新眈美小说建数据库连接的时候也是通过datasource来获取连接的,这里的abstractroutingdatasource也是通过了datasource中的getconnection方法来获取连接的。

这个类里维护了两个map来存储数据库连接信息:

@nullableprivate map<object, object> targetdatasources; @nullableprivate object defaulttargetdatasource;private boolean lenientfallback = true;private datasourcelookup datasourcelookup = new jndidatasourcelookup();@nullableprivate map<object, datasource> resolveddatasources;@nullableprivate datasource resolveddefaultdatasource;

下面对上面的几个属性进行说明:

其中第一个targetdatasources是一个map对象,在我们上面第五步创建dynamicdatasource实例的时候将多个数据源的datasource类,放入到这个map中去,这里的key是枚举类,values就是datasource类。

第二个defaulttargetdatasource是默认的数据源,就是dynamicdatasource中唯一重写的方法来给这个对象赋值的。

第三个lenientfallback是一个标识,是当指定数据源不存在的时候是否采用默认数据源,默认是true,设置为fal之后如果找不到指定数据源将会返回null.

第四个datasourcelookup是用来解析指定的数据源对象为datasource实例的。默认是jndidatasourcelookup实例,继承自datasourcelookup接口。

第五个resolveddatasources也是一个map对象,这里是存放指定数据源解析后的datasource对象。

第六个resolveddefaultdatasource是默认的解析后的datasource数据源对象上面的getconnection方法就是从这个变量中拿到datasource实例并获取连接的。

总结

本文发布于:2023-04-04 02:29:55,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/ecf907bcc7b181f794199411cc54bc28.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:Springboot动态切换数据源的具体实现与原理分析.doc

本文 PDF 下载地址:Springboot动态切换数据源的具体实现与原理分析.pdf

标签:数据源   实例   前缀   变量
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图