说明:本文章的数据源不是在配置文件中配置两个或多个数据源,在业务方面对这些数据源来回切换,本文章中的数据源是可以动态添加,修改,切换的,废话不多说。
先看工程图:
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
动态数据源添加
数据源查询
不同数据源下的表数据查询
记录一点点。。。。。。。。。。。。。。。