springboot动态数据源【非伪数据源】

说明:本文章的数据源不是在配置文件中配置两个或多个数据源,在业务方面对这些数据源来回切换,本文章中的数据源是可以动态添加,修改,切换的,废话不多说。

先看工程图:

1.pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>DemoOne</name><description>Demo project for Spring Boot</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><mybatis-spring-boot.version>1.2.0</mybatis-spring-boot.version><mysql-connector.version>5.1.39</mysql-connector.version><java.version>1.8</java.version></properties><dependencies><!--springboot相关包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- MySQL依赖导入 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- Oracle依赖导入 --><dependency><groupId>com.oracle</groupId><artifactId>ojdbc6</artifactId><version>11.2.0.3</version></dependency><!-- postgresql依赖导入 --><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><version>42.2.2</version></dependency><!--mybatis-plus相关依赖导入--><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.5.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.9</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.2</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-dbcp2</artifactId><version>2.8.0</version></dependency><!-- pagehelper分页 依赖导入--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><exclusions><exclusion><artifactId>mybatis</artifactId><groupId>org.mybatis</groupId></exclusion><exclusion><artifactId>mybatis-spring</artifactId><groupId>org.mybatis</groupId></exclusion></exclusions><version>1.2.10</version></dependency><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId></dependency><!--get set 依赖导入--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.14.8</version></dependency><!-- knife4j 增强swagger依赖导入 --><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>2.0.9</version></dependency><!-- hutool 工具包依赖导入 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.0.M3</version></dependency><!--StringUtils工具包依赖导入--><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><!--字符串转驼峰依赖导入--><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>21.0</version></dependency><!--josn依赖导入--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.28</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

2.application.yml

server:port: 9000
spring:datasource:dynamic:primary: masterdatasource:#默认数据库master:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/my_demo_01?characterEncoding=utf8&useSSL=false&autoReconnect=true&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8username: rootpassword: root#my_demo_02:#  driver-class-name: com.mysql.cj.jdbc.Driver#  url: jdbc:mysql://127.0.0.1:3306/my_demo_02?characterEncoding=utf8&useSSL=false&autoReconnect=true&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8#  username: root#  password: rootjackson:date-format: dd/MM/yyyytime-zone: GMT+8mvc:date-format: dd/MM/yyyy HH:mm:sspathmatch:matching-strategy: ant_path_matcher
logging:level:com.baomidou: debug
mybatis-plus:mapper-locations: classpath:mappers/*.xmlconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3.fs_order.sql和sys_user.sql

/*Navicat Premium Data TransferSource Server         : 本机数据库mysqlSource Server Type    : MySQLSource Server Version : 80011 (8.0.11)Source Host           : localhost:3306Source Schema         : my_demo_01Target Server Type    : MySQLTarget Server Version : 80011 (8.0.11)File Encoding         : 65001Date: 30/10/2023 11:24:09
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (`id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',`user_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',`nick_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '昵称',`age` int(4) NULL DEFAULT NULL COMMENT '年龄',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES ('a', 'zhanglong', '张龙', 30);
INSERT INTO `sys_user` VALUES ('b', 'zhaohu', '赵虎', 31);
INSERT INTO `sys_user` VALUES ('c', 'wangchao', '王朝', 32);
INSERT INTO `sys_user` VALUES ('d', 'mahan', '马汉', 33);SET FOREIGN_KEY_CHECKS = 1;
/*Navicat Premium Data TransferSource Server         : 本机数据库mysqlSource Server Type    : MySQLSource Server Version : 80011 (8.0.11)Source Host           : localhost:3306Source Schema         : my_demo_02Target Server Type    : MySQLTarget Server Version : 80011 (8.0.11)File Encoding         : 65001Date: 30/10/2023 11:24:22
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for fs_order
-- ----------------------------
DROP TABLE IF EXISTS `fs_order`;
CREATE TABLE `fs_order`  (`id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`order_num` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '订单号',`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '订单地址',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '订单表' ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of fs_order
-- ----------------------------
INSERT INTO `fs_order` VALUES ('111', '0456afa8-3c7b-40a6-a82c-544ea16ee082', '梁山八百里水泊');
INSERT INTO `fs_order` VALUES ('222', '625b2fa6-a3c5-49f9-bfc9-f8c84b5af6a0', '大运河桥');SET FOREIGN_KEY_CHECKS = 1;

4.MySpringBootApplication.java

package com.example;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;//@MapperScan("com.example.mapper")  //在数据层配置@Mapper一个功能
@SpringBootApplication
public class MySpringBootApplication {public static void main(String[] args) {SpringApplication.run(MySpringBootApplication.class, args);}
}

5.SwaggerConfig.java

package com.example.config;import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;import java.util.ArrayList;
import java.util.List;/*** @author 李庆伟* @date 2022/5/20 10:22*/
@ConditionalOnWebApplication
@Configuration
@EnableSwagger2WebMvc
@EnableKnife4j
public class SwaggerConfig {/*** Swagger2的配置文件,这里可以配置Swagger2的一些基本的内容,比如扫描的包等等* []* @return {@link Docket}* @throws* @author 李庆伟* @date 2021/12/13 16:28*/@Beanpublic Docket createRestApi() {//设置请求在父类方法中,如果在本类方法中设置请求头,则覆盖父类方法List<Parameter> pars = makeHeader();return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.basePackage(makeScan()))//.apis(RequestHandlerSelectors.basePackage(App8300.class.getPackage().getName())).build().globalOperationParameters(pars).apiInfo(apiInfo());}/*** swagger封装请求头* [pars]* @return {@link List< Parameter>}* @throws* @author 李庆伟* @date 2022/5/20 11:26*/public List<Parameter> makeHeader(){List<Parameter> pars = new ArrayList<>();ParameterBuilder token = new ParameterBuilder();token.name("Authorization").description("Authorization").modelRef(new ModelRef("string")).parameterType("header").required(false).build();pars.add(token.build());ParameterBuilder languageCode = new ParameterBuilder();languageCode.name("languageCode").description("languageCode").modelRef(new ModelRef("string")).parameterType("header").required(false).build();pars.add(languageCode.build());return pars;}public String makeScan(){return "com.example.controller";}/*** 构建API文档的详细信息函数* @return*/public ApiInfo apiInfo() {return new ApiInfoBuilder().title(makeApiName()).version("1.0").build();}public String makeApiName(){return "项目接口 API";}}

6.Result.java

package com.example.results;import com.alibaba.fastjson.JSON;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import javax.servlet.ServletResponse;
import java.io.PrintWriter;
import java.util.List;/*** @author 李庆伟* @date 2020/4/16 9:52*/
@Data
public class Result {@ApiModelProperty(value = "返回码")private int code;@ApiModelProperty(value = "返回数据")private Object data;@ApiModelProperty(value = "返回描述")private String msg;@ApiModelProperty(value = "返回长度")private long count;@ApiModelProperty(value = "详细信息")private String detailMessage;/**返回成功 */public static Result success(List<Object> data, long count){Result result = new Result();result.setCode(0);//成功result.setMsg("成功!");//提示语result.setData(data);result.setCount(count);return result;}/**返回成功 */public static Result success(List data){Result result = new Result();result.setCode(0);//成功result.setMsg("成功!");//提示语result.setData(data);result.setCount(data == null || data.size() == 0 ? 0 : data.size());return result;}/**返回成功 */public static Result successForPage(List data,Integer count){Result result = new Result();result.setCode(0);//成功result.setMsg("失败!");//提示语result.setData(data);result.setCount(count == null ? 0 : count);return result;}/**返回成功 */public static Result success(){Result result = new Result();result.setCode(0);//成功result.setMsg("成功!");//提示语return result;}/**返回成功 */public static Result success(Object object){Result result = new Result();result.setCode(0);//成功result.setMsg("成功!");//提示语result.setData(object);//返回内容return result;}/**返回失败 */public static Result error(){Result result = new Result();result.setCode(1);//失败result.setMsg("失败!");//提示语return result;}/**返回失败 */public static Result error(int code, String msg){Result result = new Result();result.setCode(code);//失败result.setMsg("失败!");//提示语return result;}/**返回失败 */public static Result error(int code, String msg, String detailMessage){Result result = new Result();result.setCode(code);//失败result.setMsg("失败!");//提示语result.setDetailMessage(detailMessage);return result;}/**Response输出Json格式 */public static void responseJson(ServletResponse response, Object data) {PrintWriter out = null;try {response.setCharacterEncoding("UTF-8");response.setContentType("application/json");out = response.getWriter();out.println(JSON.toJSONString(data));out.flush();} catch (Exception e) {System.out.println("Response输出Json异常:" + e);} finally {if (out != null) {out.close();}}}/**返回信息*/public static Result response(int code, String msg, Object data) {Result result = new Result();result.setCode(code);result.setMsg(msg);result.setData(data);return result;}
}

7.DbDataSourceConstant.java

package com.example.constant;/*** @Description: TODO* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/10/27 14:09*/
public class DbDataSourceConstant {//oracle 驱动名称public static final String ORACLE_DRIVER_CLASS_NAME = "oracle.jdbc.driver.OracleDriver";//mysql 低版本驱动名称(6.0以下)public static final String MYSQL_LOW_DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";//mysql 高版本驱动名称(6.0以上)public static final String MYSQL_HIGH_DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";//psotgresql 驱动名称public static final String PSOTGRESQL_HIGH_DRIVER_CLASS_NAME = "org.postgresql.Driver";
}

8.DbOprUtil.java

package com.example.utils;import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.example.constant.DbDataSourceConstant;
import com.example.dto.DbDataSourceDTO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Set;/*** @Description: 操作数据源工具类* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/6/30 17:14*/
@Component
public class DbOprUtil {@Autowiredprivate DataSource dataSource;@Resourceprivate DefaultDataSourceCreator dataSourceCreator;/*** @Description: 添加数据源* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/6/30 17:21*/public Set<String> addDataSource(DbDataSourceDTO sourceDTO) {// 根据数据库类型设置驱动名称switch (sourceDTO.getType().toLowerCase()) {case "mysql":sourceDTO.setDriverClassName(DbDataSourceConstant.MYSQL_HIGH_DRIVER_CLASS_NAME);break;case "oracle":sourceDTO.setDriverClassName(DbDataSourceConstant.ORACLE_DRIVER_CLASS_NAME);break;case "postgresql":sourceDTO.setDriverClassName(DbDataSourceConstant.PSOTGRESQL_HIGH_DRIVER_CLASS_NAME);break;default:return null;}boolean status = DbLinkUtil.verifyUrlConnStatus(sourceDTO.getUrl(), sourceDTO.getDriverClassName(), sourceDTO.getUsername(), sourceDTO.getPassword());if (!status) {throw new RuntimeException("数据源链接失败!");}DataSourceProperty dataSourceProperty = new DataSourceProperty();BeanUtils.copyProperties(sourceDTO, dataSourceProperty);DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);try {Connection connection = dataSource.getConnection();//String schema = connection.getSchema();///System.err.println(schema);} catch (SQLException e) {e.printStackTrace();}// 添加数据源ds.addDataSource(sourceDTO.getPoolName(), dataSource);return ds.getDataSources().keySet();}/*** @Description: 获取所以数据源* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/6/30 17:22*/public Set<String> getAllDataSource() {DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;return ds.getDataSources().keySet();}public DynamicRoutingDataSource getDataSource() {DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;return ds;}/*** @Description: 根据数据源名称删除数据源* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/6/30 17:22*/public void removeByDataSourceByName(String dataSourceName) {DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;ds.removeDataSource(dataSourceName);}/*** @Description: 手动切换到该数据源* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/6/30 17:22*/public void changeByDataSourceByName(String dataSourceName) {Set<String> set = getAllDataSource();if(set != null && set.size() > 0 && set.contains(dataSourceName)){DynamicDataSourceContextHolder.push(dataSourceName);} else {throw new RuntimeException("数据源链接切换失败!");}}}

9.DbLinkUtil.java

package com.example.utils;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;/*** @Description: 校验数据源连接是否成功* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/6/30 17:14*/
public class DbLinkUtil {/*** @Description: 校验数据源连接是否成功,不成功抛异常* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/10/27 14:37*/public static boolean verifyUrlConnStatus(String url,String driverClassName, String username, String password) {boolean flag;Connection connection = null;// 加载驱动类try {Class.forName(driverClassName);connection = DriverManager.getConnection(url, username, password);flag = true;} catch (Exception e) {e.printStackTrace();throw new RuntimeException("数据源链接不存在!");}finally {try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}return flag;}/*** @Description: 校验数据源连接是否成功,不成功返回false* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/10/27 14:37*/public static boolean verifyUrlConnStatusForB(String url,String driverClassName, String username, String password) {boolean flag;Connection connection = null;// 加载驱动类try {Class.forName(driverClassName);connection = DriverManager.getConnection(url, username, password);flag = true;} catch (Exception e) {e.printStackTrace();flag = false;}finally {try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}return flag;}
}

10.DataSourceController.java

package com.example.controller;import com.example.dto.DbDataSourceDTO;
import com.example.results.Result;
import com.example.service.DataSourceService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import javax.validation.Valid;
import java.util.List;/*** 类名称:** @author 李庆伟* @date 2023年10月27日 15:32*/
@RestController
@RequestMapping("/operDb")
@Api(tags = "数据源操作")
public class DataSourceController {@Autowiredprivate DataSourceService dataSourceService;/*** @Description: 数据源分页查询* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/7/7 14:36*/@PostMapping(value = "find")@ApiOperation(value = "查询所有数据源",notes = "查询所有数据源")@ApiResponses({@ApiResponse(code = 0, message = "ok", response= DbDataSourceDTO.class),})public Result find() {List<DbDataSourceDTO> result = dataSourceService.find();return Result.success(result);}/*** @Description: 添加数据源* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/7/7 15:31* 以下面数据为例:* poolName:my_demo_02* type:mysql* driverClassName:com.mysql.cj.jdbc.Driver* url:jdbc:mysql://127.0.0.1:3306/my_demo_02?characterEncoding=utf8&useSSL=false&autoReconnect=true&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8* username:root* password:root*/@PostMapping(value = "/add")@ApiOperation(value = "添加数据源", notes = "添加数据源", produces = "application/json")@ApiResponses({@ApiResponse(code = 0, message = "ok", response= DbDataSourceDTO.class),})public Result add(@Valid DbDataSourceDTO form) {dataSourceService.add(form);return Result.success();}/*** @Description: 测试数据源* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/7/7 15:31*/@PostMapping(value = "/checked")@ApiOperation(value = "测试数据源", notes = "测试数据源", produces = "application/json")@ApiResponses({@ApiResponse(code = 0, message = "ok", response= DbDataSourceDTO.class),})public Result checked(@Valid DbDataSourceDTO form) {dataSourceService.checked(form);return Result.success();}/*** @Description: 修改数据源* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/7/10 15:44*/@PostMapping(value = "/edit")@ApiOperation(value = "修改数据源", notes = "修改数据源", produces = "application/json")@ApiResponses({@ApiResponse(code = 0, message = "ok", response= DbDataSourceDTO.class),})public Result edit(@Valid DbDataSourceDTO form) {dataSourceService.update(form);return Result.success();}/*** @Description: 删除数据源* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/7/10 15:54*/@PostMapping(value = "/delete")@ApiOperation(value = "删除数据源", notes = "删除数据源", produces = "application/json")public Result delete(DbDataSourceDTO form) {dataSourceService.delete(form);return Result.success();}}

11.DataSourceService.java

package com.example.service;import com.example.dto.DbDataSourceDTO;import java.util.List;/*** 类名称:** @author 李庆伟* @date 2023年10月27日 15:41*/
public interface DataSourceService {//查询所有数据源List<DbDataSourceDTO> find();//添加数据源void add(DbDataSourceDTO form);//测试数据源是否能连接上void checked(DbDataSourceDTO form);//修改数据源void update(DbDataSourceDTO form);//删除数据源void delete(DbDataSourceDTO form);}

12.DataSourceServiceImpl.java

package com.example.service.impl;import com.example.constant.DbDataSourceConstant;
import com.example.dto.DbDataSourceDTO;
import com.example.service.DataSourceService;
import com.example.utils.DbLinkUtil;
import com.example.utils.DbOprUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.*;/*** 类名称:** @author 李庆伟* @date 2023年10月27日 15:41*/
@Service
public class DataSourceServiceImpl implements DataSourceService {@Autowiredprivate DbOprUtil dbOprUtil;/*** @Description: 获取所有数据源* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/10/30 9:52*/@Overridepublic List<DbDataSourceDTO> find() {Set<String> st = dbOprUtil.getAllDataSource();List<DbDataSourceDTO> list = new ArrayList<>();if(st != null && st.size() > 0){for (String str : st) {DbDataSourceDTO dbDataSourceDTO = new DbDataSourceDTO();dbDataSourceDTO.setPoolName(str);//数据源连接等信息在这里就不获取了,自己debug去找,里面都有list.add(dbDataSourceDTO);}}return list;}/*** @Description: 添加数据源* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/10/30 9:52*/@Overridepublic void add(DbDataSourceDTO form) {//验证数据源是否可用checked(form);//添加到源中成功后 在添加到数据源库中//如果成功 Add到数据源中dbOprUtil.addDataSource(form);}/*** @Description: 验证数据源是否可用* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/10/30 9:53*/@Overridepublic void checked(DbDataSourceDTO form) {//master为系统初始化数据源名称,不能被其他数据源替代和删除if(form != null && StringUtils.isNotEmpty(form.getPoolName()) && "master".equals(form.getPoolName().toLowerCase())){throw new RuntimeException("该关键字不能作为名称使用");}switch (form.getType().toLowerCase()) {case "mysql":form.setDriverClassName(DbDataSourceConstant.MYSQL_HIGH_DRIVER_CLASS_NAME);break;case "oracle":form.setDriverClassName(DbDataSourceConstant.ORACLE_DRIVER_CLASS_NAME);break;case "postgresql":form.setDriverClassName(DbDataSourceConstant.PSOTGRESQL_HIGH_DRIVER_CLASS_NAME);break;default:form.setDriverClassName("");}//判断数据源连接是否能够连接成功DbLinkUtil.verifyUrlConnStatus(form.getUrl(),form.getDriverClassName(),form.getUsername(),form.getPassword());}/*** @Description: 修改数据源* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/10/30 9:53*/@Overridepublic void update(DbDataSourceDTO form) {//验证数据源是否可用checked(form);//修改数据源库中存储数据源//删除已有数据源delete(form);//如果成功 Add到数据源中dbOprUtil.addDataSource(form);}/*** @Description: 删除数据源* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/10/30 9:53*/@Overridepublic void delete(DbDataSourceDTO form) {if(!form.getPoolName().equals("master")){dbOprUtil.removeByDataSourceByName(form.getPoolName());}}}

13.FsOrder.java

package com.example.entity;import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;/*** 类名称:订单** @author 李庆伟* @date 2023年10月27日 15:26*/
@Data
@TableName
public class FsOrder {@TableIdprivate String id;private String orderNum;//订单号private String address;//订单地址
}

14.SysUser.java

package com.example.entity;import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;/*** 类名称:用户** @author 李庆伟* @date 2023年10月27日 15:26*/
@Data
@TableName
public class SysUser {@TableIdprivate String id;private String userName;//用户名private String nickName;//昵称private Integer age;//年龄
}

15.TestController.java

package com.example.controller;import com.example.entity.FsOrder;
import com.example.entity.SysUser;
import com.example.results.Result;
import com.example.service.TestService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** 类名称:** @author 李庆伟* @date 2023年10月27日 15:32*/
@RestController
@RequestMapping("/test")
@Api(tags = "测试通过动态数据源查询数据")
public class TestController {@Autowiredprivate TestService testService;/*** @Description: 查询所有用户【在master数据库中】* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/10/30 10:58**/@PostMapping(value = "findAllSysUser")@ApiOperation(value = "查询所有用户【在master数据库中】",notes = "查询所有用户【在master数据库中】")@ApiResponses({@ApiResponse(code = 0, message = "ok", response= Result.class),})public Result findAllSysUser() {List<SysUser> result = testService.findAllSysUser();return Result.success(result);}/*** @Description: 查询所有的订单【在my_demo_02数据库中】* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/10/30 10:58** 以下面数据为例:先添加下面为例子的数据源(调用DataSourceController中的add方法,可以在swagger中做,这里就不多说了)* poolName:my_demo_02* type:mysql* driverClassName:com.mysql.cj.jdbc.Driver* url:jdbc:mysql://127.0.0.1:3306/my_demo_02?characterEncoding=utf8&useSSL=false&autoReconnect=true&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8* username:root* password:root*/@PostMapping(value = "findAllFsOrder")@ApiOperation(value = "查询所有订单【在my_demo_02数据库中】",notes = "查询所有订单【在my_demo_02数据库中】")@ApiResponses({@ApiResponse(code = 0, message = "ok", response= Result.class),})public Result findAllFsOrder() {List<FsOrder> result = testService.findAllFsOrder();return Result.success(result);}}

16.TestService.java

package com.example.service;import com.example.entity.FsOrder;
import com.example.entity.SysUser;import java.util.List;/*** 类名称:** @author 李庆伟* @date 2023年10月30日 11:02*/
public interface TestService {//查询所有的用户 【在master数据库中】List<SysUser> findAllSysUser();//查询所有的订单【在my_demo_02数据库中】List<FsOrder> findAllFsOrder();
}

17.TestServiceImpl.java

package com.example.service.impl;import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.entity.FsOrder;
import com.example.entity.SysUser;
import com.example.mapper.FsOrderMapper;
import com.example.mapper.SysUserMapper;
import com.example.service.TestService;
import com.example.utils.DbOprUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.List;/*** 类名称:** @author 李庆伟* @date 2023年10月30日 11:02*/
@Service
public class TestServiceImpl implements TestService {@Autowiredprivate DbOprUtil dbOprUtil;@Resourceprivate SysUserMapper sysUserMapper;@Resourceprivate FsOrderMapper fsOrderMapper;/*** @Description: 查询所有的用户 【在master数据库中】* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/10/30 11:04*/@Overridepublic List<SysUser> findAllSysUser() {//切换为master数据源,master为DbDataSourceDTO中的poolName(连接池名称:自定义不能重)dbOprUtil.changeByDataSourceByName("master");return sysUserMapper.selectList(new QueryWrapper<SysUser>());}/*** @Description: 查询所有的订单【在my_demo_02数据库中】* @param:* @return: {@link }* @throws:* @author:李庆伟* @date: 2023/10/30 11:04*/@Overridepublic List<FsOrder> findAllFsOrder() {//切换为my_demo_02数据源,my_demo_02为DbDataSourceDTO中的poolName(连接池名称:自定义不能重)dbOprUtil.changeByDataSourceByName("my_demo_02");return fsOrderMapper.selectList(new QueryWrapper<FsOrder>());}//@DSTransactional//多数据源事务注解//public void save() {//    dbOprUtil.changeByDataSourceByName("master");//    //insert master对应库数据//    //业务就省略了//    dbOprUtil.changeByDataSourceByName("my_demo_02");//    //insert my_demo_02对应库数据//    //业务就省略了//}
}

18.FsOrderMapper.java

package com.example.entity;import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;/*** 类名称:订单** @author 李庆伟* @date 2023年10月27日 15:26*/
@Data
@TableName
public class FsOrder {@TableIdprivate String id;private String orderNum;//订单号private String address;//订单地址
}

19.SysUser.java

package com.example.entity;import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;/*** 类名称:用户** @author 李庆伟* @date 2023年10月27日 15:26*/
@Data
@TableName
public class SysUser {@TableIdprivate String id;private String userName;//用户名private String nickName;//昵称private Integer age;//年龄
}

20.测试看效果:http://localhost:9000/doc.html

 动态数据源添加

 数据源查询

 不同数据源下的表数据查询

记录一点点。。。。。。。。。。。。。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/124574.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多输入多输出 | Matlab实现k-means-ELM(k均值聚类结合极限学习机)多输入多输出组合预测

多输入多输出 | Matlab实现k-means-ELM&#xff08;k均值聚类结合极限学习机&#xff09;多输入多输出组合预测 目录 多输入多输出 | Matlab实现k-means-ELM&#xff08;k均值聚类结合极限学习机&#xff09;多输入多输出组合预测预测效果基本描述程序设计参考资料 预测效果 基…

nodejs+python+php+微信小程序-基于安卓android的健身服务应用APP-计算机毕业设计

考虑到实际生活中在健身服务应用方面的需要以及对该系统认真的分析&#xff0c;将系统权限按管理员和用户这两类涉及用户划分。  则对于进一步提高健身服务应用发展&#xff0c;丰富健身服务应用经验能起到不少的促进作用。 健身服务应用APP能够通过互联网得到广泛的、全面的宣…

ES 8.x新特性一览(完整版)

一、看点 在 2022 年 2 月 11 日&#xff0c;Elasticsearch&#xff08;ES&#xff09;正式发布了 8.0 版本&#xff0c;而截止到 2023 年 10 月&#xff0c;历经一年半时间&#xff0c;ES官方已经连续发布了多个版本&#xff0c;最新版本为 8.10.4。这一系列的更新引入了众多引…

小红书app拉新上线了 适合网推社群和校园渠道作业

小红书app签到拉新上线了可以通过“聚量推客”进行申请&#xff0c;下面大概是要求和流程 要求网推社群渠道或者地推校园渠道&#xff0c;其它类型渠道禁止

sql--索引使用 ---覆盖索引

覆盖索引 Select 后接 * 走id索引才是最优&#xff0c;使用二级索引则需要回表&#xff08;性能稍差&#xff09; 前缀索引 Create index 索引名 on 表名( 字段名( n ) ) n数字 n代表提取这个字符串的n个构建索引 &#xff1f;&#xff1f;那么 n 为几性能是最好的呢&…

JoySSL-新兴国产品牌数字证书

随着我国对数据安全重视程度的不断提升&#xff0c;国产SSL证书越来越受到广大政府机关和企业的青睐&#xff0c;成为提升网站数据安全能力的重要技术手段。那么什么是国产SSL证书&#xff1f;国产SSL证书和普通SSL证书又有什么区别呢&#xff1f; 什么是国产SSL证书&#xff…

提高小程序SEO 排名,9招优化技巧!

在当今移动互联网时代&#xff0c;小程序已经成为企业必不可少的一种营销手段&#xff0c;而如何让用户能够更容易地找到自己的小程序&#xff0c;就需要进行SEO优化&#xff0c;提升小程序的排名&#xff0c;本文将 为大家介绍9个小程序SEO优化技巧&#xff0c;帮助您的小程序…

视频增强修复软件Topaz Video AI mac中文版支持功能

Topaz Video AI mac是一款使用人工智能技术对视频进行增强和修复的软件。它可以自动降噪、去除锐化、减少压缩失真、提高清晰度等等。Topaz Video AI可以处理各种类型的视频&#xff0c;包括低分辨率视频、老旧影片、手机录制的视频等等。 使用Topaz Video AI非常简单&#xff…

【文献分享】基于线特征的激光雷达和相机外参自动标定

论文题目&#xff1a;Line-based Automatic Extrinsic Calibration of LiDAR and Camera 中文题目&#xff1a;基于线特征的激光雷达和相机外参自动标定 作者&#xff1a;Xinyu Zhang, Shifan Zhu, Shichun Guo, Jun Li, and Huaping Liu 作者机构&#xff1a;清华大学汽车安…

nodejs+vue学生考勤综合平台的设计与实现-计算机毕业设计

在当今高度发达的信息中&#xff0c;信息管理改革已成为一种更加广泛和全面的趋势。 “学生考勤综合平台”是基于Mysql数据库&#xff0c;在 程序设计的基础上实现的。为确保中国经济的持续发展&#xff0c;信息时代日益更新&#xff0c;蓬勃发展。 因此&#xff0c;国内外技术…

git教程(2)---远程仓库操作

git教程---远程仓库 远程操作创建远程仓库克隆远程仓库HTTPSSSH 向远程仓库推送拉取远程仓库.gitignore文件给git指令起别名IssuesPull Requests 标签管理操作标签推送标签 多人协作场景一场景二 开发模型Git分支设计规范使用Gitee的DevOps平台体验项目开发流程 远程操作 创建…

50元买来的iPhone手机刷机经验

前段时间&#xff0c;家里的iPad被家人误操作&#xff0c;导致iPad变成不可使用状态。自己折腾了半天&#xff0c;没有找到解决办法。没有办法&#xff0c;只好拿到手机维修店去修理,很快就修理好了.其实也很简单--就是对iPad进行了刷机操作。当然我也看到了刷机的方法。今天&a…

完美的代价

题目&#xff1a; * 题目&#xff1a; * 回文串&#xff0c;是一种特殊的字符串&#xff0c;它从左往右和从右往左读是一样的。 * 现在给你一个串&#xff0c;它不一定是回文的&#xff0c;请你计算最少的交换次数使得该串变为完美的回文回文串。 * 例如&#xff1a;mamad * 第…

音视频技术开发周刊 | 317

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 MIT惊人再证大语言模型是世界模型&#xff01;LLM能分清真理和谎言&#xff0c;还能被人类洗脑 MIT等学者的「世界模型」第二弹来了&#xff01;这次&#xff0c;他们证明…

275. H 指数 II

275. H 指数 II 难度: 中等 来源: 每日一题 2023.10.30 给你一个整数数组 citations &#xff0c;其中 citations[i] 表示研究者的第 i 篇论文被引用的次数&#xff0c;citations 已经按照 升序排列 。计算并返回该研究者的 h 指数。 h 指数的定义&#xff1a;h 代表“高…

“探索Linux世界:从CentOS安装到常见命令使用“

目录 引言一、安装CentOS二、Linux的常见命令文件夹和目录操作命令文件编辑命令vi或vim编辑器命令模式编辑模式末行模式 总结 引言 在计算机领域&#xff0c;Linux作为一种强大而灵活的操作系统&#xff0c;在服务器、嵌入式设备和个人电脑等领域广泛应用。本文将引导您了解并…

Linux基础环境开发工具的使用(yum,vim,gcc,g++)

Linux基础环境开发工具的使用[yum,vim,gcc,g] 一.yum1.yum的快速入门1.yum安装软件2.yum卸载软件 2.yum的生态环境1.操作系统的分化2.四个问题1.服务器是谁提供的呢?2.服务器上的软件是谁提供的呢?3.为什么要提供呢?4.yum是如何得知目标服务器的地址和下载链接呢?5.软件源 …

基于单片机的空气质量检测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、主要内容二、系统方案设计2.1 系统方案设计2.2 主控制器模块选择 三、 系统软件设计4.1 程序结构分析4.2系统程序…

小红书平台用户数据分析与可视化

管理器、网页下载器、网页解析器、输出管理器这四个模块去搭建一个爬虫框架&#xff0c;将爬虫流程统一化&#xff0c;将通用的功能进行抽象&#xff0c;减少重复工作。要求实现的爬虫框架可以进行分布式爬取&#xff0c;解决爬虫的统一调度和统一去重&#xff0c;以及存储问题…