spring boot如何实现动态数据源

1,首先动态数据源需要可配置,可以动态修改,可以不需要重启相关服务器程序,达到配置修改后即及时生效.

2,所以排除了修改注解这一种方式,因为以现在的认知,注解是与代码绑定,需要修改代码,并且重新编译发布.

3,第二种xml配置,集中式管理配置,减少与代码的耦合,虽然springboot + devtools(热部署)可提供这种使应用不用重启可xml生效的能力,但不太适合提供增加的免费云数据源/服务器/虚拟主机,如原来就有的张三丰A数据源,后面动态增加B云数据,就得有三丰A,B云数据源.,数据库连接:h t t p s: // www.sanfengyun.com/datasrc/orgdatasrcA?useUnicode=true&characterEncoding=utf-8&serverTimezone=BeiJing.

4,建议用关系型数据库存储动态数据源配置,可按需要增加所需数据源,然后再根据数据库配置动态切换不同数据源.

5,说到连接数据库,那当然需要一个静态数据库,用来获取数据库配置数据,然后根据静态数据库的数据库配置数据生成动态数据.

如下是数据库配置实体类

/**
 * 

* 表名:[data_src],数据源表 实体类 *

* @author * @since 2020-10-24 */ @Entity @Table(name="data_src") @JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" }) @TableName("data_src") @ApiModel(value="DataSrc对象", description="数据源表") public class DataSrc extends Model { @ApiModelProperty(value = "主键") @TableId(value = "id", type = IdType.ID_WORKER) @Id @Column(name="id") private Long id; @ApiModelProperty(value = "版本") @TableField("version") @Column(name="version") @com.baomidou.mybatisplus.annotation.Version @javax.persistence.Version private Integer version; @ApiModelProperty(value = "创建人") @TableField(value = "create_by", fill = FieldFill.INSERT) @Column(name="create_by") private Long createBy; @ApiModelProperty(value = "创建人名称") @TableField("create_by_name") @Column(name="create_by_name") private String createByName; @ApiModelProperty(value = "创建时间") @TableField(value = "create_time", fill = FieldFill.INSERT) @Column(name="create_time") private LocalDateTime createTime; @ApiModelProperty(value = "更新人") @TableField(value = "last_up_by", fill = FieldFill.INSERT_UPDATE) @Column(name="last_up_by") private Long lastUpBy; @ApiModelProperty(value = "更新人名称") @TableField("last_up_by_name") @Column(name="last_up_by_name") private String lastUpByName; @ApiModelProperty(value = "更新时间") @TableField(value = "last_up_time", fill = FieldFill.INSERT_UPDATE) @Column(name="last_up_time") private LocalDateTime lastUpTime; @ApiModelProperty(value = "是否删除(1/0)默认0") @TableField("is_del") @Column(name="is_del") @TableLogic private Integer isDel; @ApiModelProperty(value = "备注") @TableField("remark") @Column(name="remark") private String remark; @ApiModelProperty(value = "编码") @TableField("code") @Column(name="code") private String code; @ApiModelProperty(value = "数据源名称") @TableField("name") @Column(name="name") private String name; @ApiModelProperty(value = "用户名,密码,url,driverClassName,还有其他参数等等,json字符串") @TableField("data_src_property") @Column(name="data_src_property") private String dataSrcProperty; @ApiModelProperty(value = "数据源类型id") @TableField("dyna_data_src_type_id") @Column(name="dyna_data_src_type_id") private Long dynaDataSrcTypeId; /** * 获取[id] * @return id :[主键] */ public Long getId() { return id; } /** * 设置[id] * @param id :[主键] */ public DataSrc setId(Long id) { this.id = id; return this; } /** * 获取[version] * @return version :[版本] */ public Integer getVersion() { return version; } /** * 设置[version] * @param version :[版本] */ public DataSrc setVersion(Integer version) { this.version = version; return this; } /** * 获取[create_by] * @return createBy :[创建人] */ public Long getCreateBy() { return createBy; } /** * 设置[create_by] * @param createBy :[创建人] */ public DataSrc setCreateBy(Long createBy) { this.createBy = createBy; return this; } /** * 获取[create_by_name] * @return createByName :[创建人名称] */ public String getCreateByName() { return createByName; } /** * 设置[create_by_name] * @param createByName :[创建人名称] */ public DataSrc setCreateByName(String createByName) { this.createByName = createByName; return this; } /** * 获取[create_time] * @return createTime :[创建时间] */ public LocalDateTime getCreateTime() { return createTime; } /** * 设置[create_time] * @param createTime :[创建时间] */ public DataSrc setCreateTime(LocalDateTime createTime) { this.createTime = createTime; return this; } /** * 获取[last_up_by] * @return lastUpBy :[更新人] */ public Long getLastUpBy() { return lastUpBy; } /** * 设置[last_up_by] * @param lastUpBy :[更新人] */ public DataSrc setLastUpBy(Long lastUpBy) { this.lastUpBy = lastUpBy; return this; } /** * 获取[last_up_by_name] * @return lastUpByName :[更新人名称] */ public String getLastUpByName() { return lastUpByName; } /** * 设置[last_up_by_name] * @param lastUpByName :[更新人名称] */ public DataSrc setLastUpByName(String lastUpByName) { this.lastUpByName = lastUpByName; return this; } /** * 获取[last_up_time] * @return lastUpTime :[更新时间] */ public LocalDateTime getLastUpTime() { return lastUpTime; } /** * 设置[last_up_time] * @param lastUpTime :[更新时间] */ public DataSrc setLastUpTime(LocalDateTime lastUpTime) { this.lastUpTime = lastUpTime; return this; } /** * 获取[is_del] * @return isDel :[是否删除(1/0)默认0] */ public Integer getIsDel() { return isDel; } /** * 设置[is_del] * @param isDel :[是否删除(1/0)默认0] */ public DataSrc setIsDel(Integer isDel) { this.isDel = isDel; return this; } /** * 获取[remark] * @return remark :[备注] */ public String getRemark() { return remark; } /** * 设置[remark] * @param remark :[备注] */ public DataSrc setRemark(String remark) { this.remark = remark; return this; } /** * 获取[code] * @return code :[编码] */ public String getCode() { return code; } /** * 设置[code] * @param code :[编码] */ public DataSrc setCode(String code) { this.code = code; return this; } /** * 获取[name] * @return name :[数据源名称] */ public String getName() { return name; } /** * 设置[name] * @param name :[数据源名称] */ public DataSrc setName(String name) { this.name = name; return this; } /** * 获取[data_src_property] * @return dataSrcProperty :[用户名,密码,url,driverClassName,还有其他参数等等,json字符串] */ public String getDataSrcProperty() { return dataSrcProperty; } /** * 设置[data_src_property] * @param dataSrcProperty :[用户名,密码,url,driverClassName,还有其他参数等等,json字符串] */ public DataSrc setDataSrcProperty(String dataSrcProperty) { this.dataSrcProperty = dataSrcProperty; return this; } /** * 获取[dyna_data_src_type_id] * @return dynaDataSrcTypeId :[数据源类型id] */ public Long getDynaDataSrcTypeId() { return dynaDataSrcTypeId; } /** * 设置[dyna_data_src_type_id] * @param dynaDataSrcTypeId :[数据源类型id] */ public DataSrc setDynaDataSrcTypeId(Long dynaDataSrcTypeId) { this.dynaDataSrcTypeId = dynaDataSrcTypeId; return this; } }

6,谈到数据来源,那肯定少不了,不同的连接池类型,以下是数据源类型实体

/**
 * 

* 表名:[dyna_data_src_type],数据源类型表 druidDataSource,com.alibaba.druid.pool.DruidDataSourc 实体类 *

* @author * @since 2020-10-24 */ @Entity @Table(name="data_src_type") @JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" }) @TableName("data_src_type") @ApiModel(value="DataSrcType对象", description="数据源类型表 druidDataSource,com.alibaba.druid.pool.DruidDataSourc") public class DataSrcType extends Model { @ApiModelProperty(value = "主键") @TableId(value = "id", type = IdType.ID_WORKER) @Id @Column(name="id") private Long id; @ApiModelProperty(value = "版本") @TableField("version") @Column(name="version") @com.baomidou.mybatisplus.annotation.Version @javax.persistence.Version private Integer version; @ApiModelProperty(value = "创建人") @TableField(value = "create_by", fill = FieldFill.INSERT) @Column(name="create_by") private Long createBy; @ApiModelProperty(value = "创建人名称") @TableField("create_by_name") @Column(name="create_by_name") private String createByName; @ApiModelProperty(value = "创建时间") @TableField(value = "create_time", fill = FieldFill.INSERT) @Column(name="create_time") private LocalDateTime createTime; @ApiModelProperty(value = "更新人") @TableField(value = "last_up_by", fill = FieldFill.INSERT_UPDATE) @Column(name="last_up_by") private Long lastUpBy; @ApiModelProperty(value = "更新人名称") @TableField("last_up_by_name") @Column(name="last_up_by_name") private String lastUpByName; @ApiModelProperty(value = "更新时间") @TableField(value = "last_up_time", fill = FieldFill.INSERT_UPDATE) @Column(name="last_up_time") private LocalDateTime lastUpTime; @ApiModelProperty(value = "是否删除(1/0)默认0") @TableField("is_del") @Column(name="is_del") @TableLogic private Integer isDel; @ApiModelProperty(value = "备注") @TableField("remark") @Column(name="remark") private String remark; @ApiModelProperty(value = "编码") @TableField("code") @Column(name="code") private String code; @ApiModelProperty(value = "类型名称") @TableField("name") @Column(name="name") private String name; @ApiModelProperty(value = "类名") @TableField("class_name") @Column(name="class_name") private String className; /** * 获取[id] * @return id :[主键] */ public Long getId() { return id; } /** * 设置[id] * @param id :[主键] */ public DataSrcType setId(Long id) { this.id = id; return this; } /** * 获取[version] * @return version :[版本] */ public Integer getVersion() { return version; } /** * 设置[version] * @param version :[版本] */ public DataSrcType setVersion(Integer version) { this.version = version; return this; } /** * 获取[create_by] * @return createBy :[创建人] */ public Long getCreateBy() { return createBy; } /** * 设置[create_by] * @param createBy :[创建人] */ public DataSrcType setCreateBy(Long createBy) { this.createBy = createBy; return this; } /** * 获取[create_by_name] * @return createByName :[创建人名称] */ public String getCreateByName() { return createByName; } /** * 设置[create_by_name] * @param createByName :[创建人名称] */ public DataSrcType setCreateByName(String createByName) { this.createByName = createByName; return this; } /** * 获取[create_time] * @return createTime :[创建时间] */ public LocalDateTime getCreateTime() { return createTime; } /** * 设置[create_time] * @param createTime :[创建时间] */ public DataSrcType setCreateTime(LocalDateTime createTime) { this.createTime = createTime; return this; } /** * 获取[last_up_by] * @return lastUpBy :[更新人] */ public Long getLastUpBy() { return lastUpBy; } /** * 设置[last_up_by] * @param lastUpBy :[更新人] */ public DataSrcType setLastUpBy(Long lastUpBy) { this.lastUpBy = lastUpBy; return this; } /** * 获取[last_up_by_name] * @return lastUpByName :[更新人名称] */ public String getLastUpByName() { return lastUpByName; } /** * 设置[last_up_by_name] * @param lastUpByName :[更新人名称] */ public DataSrcType setLastUpByName(String lastUpByName) { this.lastUpByName = lastUpByName; return this; } /** * 获取[last_up_time] * @return lastUpTime :[更新时间] */ public LocalDateTime getLastUpTime() { return lastUpTime; } /** * 设置[last_up_time] * @param lastUpTime :[更新时间] */ public DataSrcType setLastUpTime(LocalDateTime lastUpTime) { this.lastUpTime = lastUpTime; return this; } /** * 获取[is_del] * @return isDel :[是否删除(1/0)默认0] */ public Integer getIsDel() { return isDel; } /** * 设置[is_del] * @param isDel :[是否删除(1/0)默认0] */ public DataSrcType setIsDel(Integer isDel) { this.isDel = isDel; return this; } /** * 获取[remark] * @return remark :[备注] */ public String getRemark() { return remark; } /** * 设置[remark] * @param remark :[备注] */ public DataSrcType setRemark(String remark) { this.remark = remark; return this; } /** * 获取[code] * @return code :[编码] */ public String getCode() { return code; } /** * 设置[code] * @param code :[编码] */ public DataSrcType setCode(String code) { this.code = code; return this; } /** * 获取[name] * @return name :[类型名称] */ public String getName() { return name; } /** * 设置[name] * @param name :[类型名称] */ public DataSrcType setName(String name) { this.name = name; return this; } /** * 获取[class_name] * @return className :[类名] */ public String getClassName() { return className; } /** * 设置[class_name] * @param className :[类名] */ public DataSrcType setClassName(String className) { this.className = className; return this; } }

7,有了可配置的实体,就到了初始化动态数据源&创建新数据源&切换数据源,继承AbstractRoutingDataSource.

切换数据源changeDataSource(rpSqlCfg);

private void changeDataSource(RpSqlCfg rpSqlCfg) throws Exception {
        String sysCodeExt=rpSqlCfg.getTenantId()+"&"+rpSqlCfg.getOrgId()+"&"+rpSqlCfg.getSysCode();
        String key=ClientDyna.getDbnaDSrcKey(sysCodeExt,rpSqlCfg.getModelCode(),rpSqlCfg.getDataSrcId());
        boolean checkFlag=ClientDyna.check(sysCodeExt,
                rpSqlCfg.getModelCode(),rpSqlCfg.getDataSrcId());
        if(checkFlag){
            logger.error("数据源实体不存在内存中,需要加载");
            //不存在内存中,需要加载
            ReturnDto relVReturnDto=dataSrcModRelVFeignClient.getDSMRV(rpSqlCfg.getTenantId(),rpSqlCfg.getOrgId(),rpSqlCfg.getSysCode(),
                    rpSqlCfg.getModelCode(),rpSqlCfg.getDataSrcId());
            DataSrcModRelV dataSrcModRelV=relVReturnDto.getData();
            if(dataSrcModRelV==null){
                throw  new Exception("没找到数据源相关信息!");
            }
            ClientDyna.addMap(dataSrcModRelV);//添加缓存
            dynaRoutingDataSource.createDataSource(sysCodeExt, dataSrcModRelV.getModelCode(),dataSrcModRelV.getDataSrcId());//创建数据源
        }else{
            logger.error("数据源实体存在内存中,不需要加载");
        }
        dynaRoutingDataSource.selectDataSource(key);//切换数据源
    }

8,创建数据源 

public  Object createDataSource(String sysCode,String modelCode,Long dataSrcId) throws Exception {
        String key=ClientDyna.getDbnaDSrcKey(sysCode,modelCode, dataSrcId);
        return createDataSource(key);
    }
	
public static  Object createDataSource(String key) throws Exception {
		 DataSrcModRelV vo = getByKey(key);
	    // Object ds = null;
	     if(vo != null) {	     
	    	// System.out.println("vo.getClassName()="+vo.getClassName());
	    	 //System.out.println("vo.getDataSrcProperty()="+vo.getDataSrcProperty());
			 logger.error("vo.getClassName()="+vo.getClassName());
			 logger.error("vo.getDataSrcProperty()="+vo.getDataSrcProperty());
	    	 Class cc=Class.forName(vo.getClassName());
	    	 Object c =JSONUtil.readObject(vo.getDataSrcProperty(), cc);
	         return c;
	     } else {
	         throw new Exception("当前 cache not exists datasource[createDataSource]");
	     }
	 }

9,更改当前数据源 

public Object selectDataSource(String key) throws Exception {
        if (!this.targetDataSources.containsKey(key)) {
            Object o=this.createDataSource(key);
            DBContextHolder.setDBType(key);
            return o;
        }
        DBContextHolder.setDBType(key);
        return this.targetDataSources.get(key);
    }

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

一键部署及管理app

异界:

[国服] 天秤座公会战全阶段作业-公主连接自动刀auto

你可能感兴趣的:(IT,程序员,1024程序员节)