Spring动态添加数据源(全自动)

一、使用场景

1、现在网上所有写的动态数据源,都是假动态数据,都是预先知道要连接几个数据库,但这不满足具体真正需要动态添加连接数据库的需求;

2、在很多业务场景下,如项目默认连一个主数据库,服务启动后,因业务不停的变更,需要动态连接其它数据库处理数据,关键点是其它数据库,在服务启动前是不知道连接地址的,所以其它数据库的地址是无法预先配置在application.yml文件中

二、因项目需求,需要真正动态连接其它库处理数据

1、做之前,百度网上搜,都是假动态数据源,为实现上面的真正动态添加数据,也花了几天时间才集成起,废话不多说

三、准备工作

1、准备三个数据,db_main,db_add01,db_add02,其中db_main为项目起动,默认连的主数据库,为了下面测试方便,我在三个数据库中创建了不同的三张表sys_company、sys_role、sys_user,以表示查询的数据不同,数据来源于不同的数据库,截图如下

application.yml中配置主数据库接信息

server:port: 8085
spring:application:name: mydatadatasource:username: rootpassword: 123456url: jdbc:mysql://192.168.137.202:3306/db_main?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8druid:initialSize: 5minIdle: 5maxActive: 20maxWait: 60000#配置监控属性: 在druid-starter的: com.alibaba.druid.spring.boot.autoconfigure.stat包下进行的逻辑配置# WebStatFilter配置,stat-view-servlet:#配置DruidStatViewServlet的访问地址。后台监控页面的访问地址url-pattern: /druid/*#禁用HTML页面上的“重置”功能,会把所有监控的数据全部清空,一般不使用reset-enable: false#监控页面登录的用户名login-username: admin#监控页面登录的密码login-password: 123456#白名单allow:#黑名单deny:

 2、动态添加数据库核心代码

/*** 添加私有数据源* @param dbName 数据库名* @param url* @param username* @param password*/public void addDataSource(String dbName,String url,String username,String password){if(!StringUtils.isEmpty(dbName)) {if (dataSourcesMap.get(dbName) == null) {DataSource dataSource = druidDataSource(url, username, password);dataSourcesMap.put(dbName, dataSource);super.setTargetDataSources(dataSourcesMap);super.afterPropertiesSet();} else {DruidDataSource dataSource = (DruidDataSource) dataSourcesMap.get(dbName);if (!dataSource.isEnable()) {try {dataSource.restart();} catch (SQLException e) {e.printStackTrace();}}}}}/*** 移出对应数据源* @param dbName*/public void removeDataSource(String dbName){if(dataSourcesMap.get(dbName)!=null) {DruidDataSource dataSource= (DruidDataSource)dataSourcesMap.get(dbName);dataSourcesMap.remove(dbName);dataSource.close();super.afterPropertiesSet();}}

3、动态切换数据库

//线程本地环境private static final ThreadLocal dataSources = new ThreadLocal();//设置数据源,动态切换,就是调用这个setDataSource方法public static void setDataSource(String customerType) {dataSources.set(customerType);}//获取数据源public static String getDataSource() {return (String) dataSources.get();}//清除数据源public static void clearDataSource() {dataSources.remove();}

4、controller接口测试,代码如下

/*** 查询主库数据*/@GetMapping (value="/findMain")public SysCompany findMain(@RequestParam(defaultValue = "C190829X5R")String id) {DataSourceHolder.setDataSource("db_main");SysCompany company = (SysCompany)dataService.findTById(SysCompany.class,id);return company;}/*** 查询db_add01号库数据* dbName 对应数据库名称*/@GetMapping (value="/addDB")public String addDB(@RequestParam(defaultValue = "db_add01") String dbName, @RequestParam(defaultValue = "jdbc:mysql://192.168.137.202:3306/db_add01") String url,@RequestParam(defaultValue = "root")String username, @RequestParam(defaultValue = "123456")String password) {dynamicDataSource.addDataSource(dbName,url,username,password);return "添加成功";}/**** 查询db_add01号库数据* dbName 对应数据库名称*/@GetMapping (value="/findDb01")public SysUser findDb01(@RequestParam(defaultValue = "db_add01")String dbName,@RequestParam(defaultValue = "5")String id) {DataSourceHolder.setDataSource(dbName);SysUser sysUser = (SysUser)dataService.findTById(SysUser.class,id);return sysUser;}/*** 查询db_add02号库数据* dbName 对应数据库名称*/@GetMapping (value="/findDb02")public SysRole findDb02(@RequestParam(defaultValue = "db_add02")String dbName,@RequestParam(defaultValue = "1")String id) {DataSourceHolder.setDataSource(dbName);SysRole sysRole = (SysRole)dataService.findTById(SysRole.class,id);return sysRole;}

四、测试

1、查询主库数据,GET请求 http://localhost:8085/app/findMain?id=C190829X5R

 2、为了演示效果,我们在不添加db_add01库之前,查询一下db_add01库中的表sys_user,是要报错的 http://localhost:8085/app/findDb01?dbName=db_add01&id=5

 3、添加db_add01号库,后查询数据

添加库:http://localhost:8085/app/addDB?dbName=db_add02&url=jdbc:mysql://192.168.137.202:3306/db_add02&username=root&password=123456

上面db_add01添加之后,查询db_add01,数据可以顺利查询出来: 

http://localhost:8085/app/findDb01?dbName=db_add01&id=5

 五、总结

1、在db_add01添加之前,查询db_add01库中的表sys_user,服务报错,找不到对应的表

2、在通过接口添加db_add01数据库之后,可以正常查询出数据

3、如需要源代码,可下载 百度网盘 请输入提取码


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部