Browse Source

数据源切换、开放权限

LLL 1 year ago
parent
commit
3f317ca43a

+ 5 - 1
jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java

@@ -130,7 +130,7 @@ public class ShiroConfig {
         filterChainDefinitionMap.put("/jmreport/**", "anon");
         filterChainDefinitionMap.put("/**/*.js.map", "anon");
         filterChainDefinitionMap.put("/**/*.css.map", "anon");
-        
+
         //大屏模板例子
         filterChainDefinitionMap.put("/test/bigScreen/**", "anon");
         filterChainDefinitionMap.put("/bigscreen/template1/**", "anon");
@@ -145,6 +145,10 @@ public class ShiroConfig {
         filterChainDefinitionMap.put("/vxeSocket/**", "anon");//JVxeTable无痕刷新示例
 
 
+        //修改数据源切换
+        filterChainDefinitionMap.put("/dataSourceSwitch/switchDataSource/**", "anon");//JVxeTable无痕刷新示例
+
+
         //性能监控,放开排除会存在安全漏洞泄露TOEKN(durid连接池也有)
         //filterChainDefinitionMap.put("/actuator/**", "anon");
 

+ 10 - 2
jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/JeecgSystemApplication.java

@@ -4,9 +4,11 @@ import lombok.extern.slf4j.Slf4j;
 import org.jeecg.common.util.oConvertUtils;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
 import org.springframework.boot.builder.SpringApplicationBuilder;
 import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
 import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
 import org.springframework.core.env.Environment;
 
 import java.net.InetAddress;
@@ -15,10 +17,15 @@ import java.net.UnknownHostException;
 /**
 * 单体启动类
 * 报错提醒: 未集成mongo报错,可以打开启动类上面的注释 exclude={MongoAutoConfiguration.class}
+ *
+ * 由于要定义多个数据源,所以在Spring Boot数据源自动配置类中就无法确定导入哪个数据源来完成初始化,
+ * 所以需要禁用掉Spring Boot的数据源自动配置类,然后使用我们自定义的数据源配置类来完成数据源的初始化与管理。
 */
 @Slf4j
-@SpringBootApplication
+//@SpringBootApplication()
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})//-----------改的地方
 //@EnableAutoConfiguration(exclude={MongoAutoConfiguration.class})
+@EnableAspectJAutoProxy //开启Spring Boot对AOP的支持-----------改的地方
 public class JeecgSystemApplication extends SpringBootServletInitializer {
 
     @Override
@@ -27,6 +34,7 @@ public class JeecgSystemApplication extends SpringBootServletInitializer {
     }
 
     public static void main(String[] args) throws UnknownHostException {
+//        SpringApplication.run(JeecgSystemApplication.class, args);//-----------改的地方
         ConfigurableApplicationContext application = SpringApplication.run(JeecgSystemApplication.class, args);
         Environment env = application.getEnvironment();
         String ip = InetAddress.getLocalHost().getHostAddress();
@@ -41,4 +49,4 @@ public class JeecgSystemApplication extends SpringBootServletInitializer {
 
     }
 
-}
+}

+ 6 - 1
jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml

@@ -129,11 +129,16 @@ spring:
         # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
         connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
       datasource:
-        master:
+        master: ## 声明第一个数据源所需的数据
           url: jdbc:mysql://152.136.206.27:3306/yecai?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
           username: itdm-boot
           password:  itdm-boot@2023
           driver-class-name: com.mysql.cj.jdbc.Driver
+        slave:
+          url: jdbc:mysql://localhost:3306/kezhikeshi?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
+          username: root
+          password: 302201
+          driver-class-name: com.mysql.cj.jdbc.Driver
           # 多数据源配置
           #multi-datasource1:
           #url: jdbc:mysql://localhost:3306/jeecg-boot2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai

+ 14 - 0
module_kzks/src/main/java/org/jeecg/modules/dataSourceSwitch/annotation/TargetDataSource.java

@@ -0,0 +1,14 @@
+package org.jeecg.modules.dataSourceSwitch.annotation;
+
+import org.jeecg.modules.dataSourceSwitch.enums.DataSourceType;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.TYPE,ElementType.METHOD})//TYPE 用于描述类、接口(包括注解类型) 或enum声明。METHOD:该注解只能声明在一个类的方法前。
+@Retention(RetentionPolicy.RUNTIME)//注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
+@Documented//如果一个注解@B,被@Documented标注,那么被@B修饰的类,生成文档时,会显示@B。如果@B没有被@Documented标准,最终生成的文档中就不会显示@B。
+public @interface TargetDataSource {
+
+    DataSourceType value() default DataSourceType.MASTER;
+}
+

+ 70 - 0
module_kzks/src/main/java/org/jeecg/modules/dataSourceSwitch/aspect/TargetDataSourceAspect.java

@@ -0,0 +1,70 @@
+package org.jeecg.modules.dataSourceSwitch.aspect;
+
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.jeecg.modules.customColumns.entity.CustomColumns;
+import org.jeecg.modules.customColumns.service.ICustomColumnsService;
+import org.jeecg.modules.dataSourceSwitch.annotation.TargetDataSource;
+import org.jeecg.modules.dataSourceSwitch.entity.SwitchDataSource;
+import org.jeecg.modules.dataSourceSwitch.manage.DataSourceManagement;
+import org.jeecg.modules.dataSourceSwitch.service.ISwitchDataSourceService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+@Aspect
+@Slf4j
+public class TargetDataSourceAspect {
+
+    @Autowired
+    private ISwitchDataSourceService switchDataSourceService;
+
+    @Pointcut("@annotation(org.jeecg.modules.dataSourceSwitch.annotation.TargetDataSource) || @within(org.jeecg.modules.dataSourceSwitch.annotation.TargetDataSource)")
+    public void dsPointCut() {
+    }
+
+    @Before("dsPointCut()")
+    public void around(JoinPoint point) throws Throwable {
+
+//        TargetDataSource annotation = null;
+//        Class<? extends Object> target = point.getTarget().getClass();
+//        if(target.isAnnotationPresent(TargetDataSource.class)){
+//            // 判断类上是否标注着注解
+//            annotation = target.getAnnotation(TargetDataSource.class);
+//            log.info("类上标注了注解");
+//        }else{
+//            Method method = ((MethodSignature) point.getSignature()).getMethod();
+//            if(method.isAnnotationPresent(TargetDataSource.class)){
+//                // 判断方法上是否标注着注解,如果类和方法上都没有标注,则报错
+//                annotation = method.getAnnotation(TargetDataSource.class);
+//                log.info("方法上标注了注解");
+//            }else{
+//                throw new RuntimeException("@TargetDataSource注解只能用于类或者方法上, 错误出现在:[" +
+//                        target.toString() +" " + method.toString() + "];");
+//            }
+//        }
+
+        // 切换数据源 0主数据源,1其他数据源
+        SwitchDataSource switchDataSource = switchDataSourceService.getById(1);
+        Integer type = Integer.valueOf(switchDataSource.getType());
+        System.out.println("==========================="+type+"========================");
+        if (type != null && type == 0) {
+            DataSourceManagement.flag.set("MASTER");
+        } else if (type != null && type == 1) {
+            DataSourceManagement.flag.set("SLAVE");
+        }
+//        DataSourceManagement.flag.set(annotation.value().name());
+    }
+
+}
+

+ 30 - 0
module_kzks/src/main/java/org/jeecg/modules/dataSourceSwitch/config/DataSourceConfig.java

@@ -0,0 +1,30 @@
+package org.jeecg.modules.dataSourceSwitch.config;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+
+@Configuration
+public class DataSourceConfig {
+
+    //@ConfigurationProperties注解用于将YAML中指定的数据创建成指定的对象,但是,YAML中的数据必须要与对象对象中的属性同名,不然无法由Spring Boot完成赋值。
+    @Bean(name = "master")
+    @ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.master")
+    public DataSource dataSource1(){
+        DruidDataSource build = DruidDataSourceBuilder.create().build();
+        return build;
+    }
+
+
+    @Bean(name = "slave")
+    @ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.slave")
+    public DataSource dataSource2(){
+        DruidDataSource build = DruidDataSourceBuilder.create().build();
+        return build;
+    }
+}
+

+ 177 - 0
module_kzks/src/main/java/org/jeecg/modules/dataSourceSwitch/controller/SwitchDataSourceController.java

@@ -0,0 +1,177 @@
+package org.jeecg.modules.dataSourceSwitch.controller;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.system.query.QueryGenerator;
+import org.jeecg.common.util.oConvertUtils;
+import org.jeecg.modules.dataSourceSwitch.entity.SwitchDataSource;
+import org.jeecg.modules.dataSourceSwitch.service.ISwitchDataSourceService;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.extern.slf4j.Slf4j;
+
+import org.jeecgframework.poi.excel.ExcelImportUtil;
+import org.jeecgframework.poi.excel.def.NormalExcelConstants;
+import org.jeecgframework.poi.excel.entity.ExportParams;
+import org.jeecgframework.poi.excel.entity.ImportParams;
+import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
+import org.jeecg.common.system.base.controller.JeecgController;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+import org.springframework.web.servlet.ModelAndView;
+import com.alibaba.fastjson.JSON;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.jeecg.common.aspect.annotation.AutoLog;
+
+ /**
+ * @Description: switch_data_source
+ * @Author: jeecg-boot
+ * @Date:   2023-08-27
+ * @Version: V1.0
+ */
+@Api(tags="switch_data_source")
+@RestController
+@RequestMapping("/dataSourceSwitch/switchDataSource")
+@Slf4j
+public class SwitchDataSourceController extends JeecgController<SwitchDataSource, ISwitchDataSourceService> {
+	@Autowired
+	private ISwitchDataSourceService switchDataSourceService;
+	
+	/**
+	 * 分页列表查询
+	 *
+	 * @param switchDataSource
+	 * @param pageNo
+	 * @param pageSize
+	 * @param req
+	 * @return
+	 */
+	//@AutoLog(value = "switch_data_source-分页列表查询")
+	@ApiOperation(value="switch_data_source-分页列表查询", notes="switch_data_source-分页列表查询")
+	@GetMapping(value = "/list")
+	public Result<IPage<SwitchDataSource>> queryPageList(SwitchDataSource switchDataSource,
+								   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
+								   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
+								   HttpServletRequest req) {
+		QueryWrapper<SwitchDataSource> queryWrapper = QueryGenerator.initQueryWrapper(switchDataSource, req.getParameterMap());
+		Page<SwitchDataSource> page = new Page<SwitchDataSource>(pageNo, pageSize);
+		IPage<SwitchDataSource> pageList = switchDataSourceService.page(page, queryWrapper);
+		return Result.OK(pageList);
+	}
+	
+	/**
+	 *   添加
+	 *
+	 * @param switchDataSource
+	 * @return
+	 */
+	@AutoLog(value = "switch_data_source-添加")
+	@ApiOperation(value="switch_data_source-添加", notes="switch_data_source-添加")
+	//@RequiresPermissions("org.jeecg.modules:switch_data_source:add")
+	@PostMapping(value = "/add")
+	public Result<String> add(@RequestBody SwitchDataSource switchDataSource) {
+		switchDataSourceService.save(switchDataSource);
+		return Result.OK("添加成功!");
+	}
+	
+	/**
+	 *  编辑
+	 *
+	 * @param switchDataSource
+	 * @return
+	 */
+	@AutoLog(value = "switch_data_source-编辑")
+	@ApiOperation(value="switch_data_source-编辑", notes="switch_data_source-编辑")
+	//@RequiresPermissions("org.jeecg.modules:switch_data_source:edit")
+	@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
+	public Result<String> edit(@RequestBody SwitchDataSource switchDataSource) {
+		switchDataSourceService.updateById(switchDataSource);
+		return Result.OK("编辑成功!");
+	}
+	
+	/**
+	 *   通过id删除
+	 *
+	 * @param id
+	 * @return
+	 */
+	@AutoLog(value = "switch_data_source-通过id删除")
+	@ApiOperation(value="switch_data_source-通过id删除", notes="switch_data_source-通过id删除")
+	//@RequiresPermissions("org.jeecg.modules:switch_data_source:delete")
+	@DeleteMapping(value = "/delete")
+	public Result<String> delete(@RequestParam(name="id",required=true) String id) {
+		switchDataSourceService.removeById(id);
+		return Result.OK("删除成功!");
+	}
+	
+	/**
+	 *  批量删除
+	 *
+	 * @param ids
+	 * @return
+	 */
+	@AutoLog(value = "switch_data_source-批量删除")
+	@ApiOperation(value="switch_data_source-批量删除", notes="switch_data_source-批量删除")
+	//@RequiresPermissions("org.jeecg.modules:switch_data_source:deleteBatch")
+	@DeleteMapping(value = "/deleteBatch")
+	public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
+		this.switchDataSourceService.removeByIds(Arrays.asList(ids.split(",")));
+		return Result.OK("批量删除成功!");
+	}
+	
+	/**
+	 * 通过id查询
+	 *
+	 * @param id
+	 * @return
+	 */
+	//@AutoLog(value = "switch_data_source-通过id查询")
+	@ApiOperation(value="switch_data_source-通过id查询", notes="switch_data_source-通过id查询")
+	@GetMapping(value = "/queryById")
+	public Result<SwitchDataSource> queryById(@RequestParam(name="id",required=true) String id) {
+		SwitchDataSource switchDataSource = switchDataSourceService.getById(id);
+		if(switchDataSource==null) {
+			return Result.error("未找到对应数据");
+		}
+		return Result.OK(switchDataSource);
+	}
+
+    /**
+    * 导出excel
+    *
+    * @param request
+    * @param switchDataSource
+    */
+    //@RequiresPermissions("org.jeecg.modules:switch_data_source:exportXls")
+    @RequestMapping(value = "/exportXls")
+    public ModelAndView exportXls(HttpServletRequest request, SwitchDataSource switchDataSource) {
+        return super.exportXls(request, switchDataSource, SwitchDataSource.class, "switch_data_source");
+    }
+
+    /**
+      * 通过excel导入数据
+    *
+    * @param request
+    * @param response
+    * @return
+    */
+    //@RequiresPermissions("switch_data_source:importExcel")
+    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
+    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
+        return super.importExcel(request, response, SwitchDataSource.class);
+    }
+
+}

+ 43 - 0
module_kzks/src/main/java/org/jeecg/modules/dataSourceSwitch/entity/SwitchDataSource.java

@@ -0,0 +1,43 @@
+package org.jeecg.modules.dataSourceSwitch.entity;
+
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import lombok.Data;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.jeecg.common.aspect.annotation.Dict;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * @Description: switch_data_source
+ * @Author: jeecg-boot
+ * @Date:   2023-08-27
+ * @Version: V1.0
+ */
+@Data
+@TableName("switch_data_source")
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value="switch_data_source对象", description="switch_data_source")
+public class SwitchDataSource implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	/**id*/
+	@TableId(type = IdType.ASSIGN_ID)
+    @ApiModelProperty(value = "id")
+    private java.lang.Integer id;
+	/**数据源:0默认数据源,1其他数据源*/
+	@Excel(name = "数据源:0默认数据源,1其他数据源", width = 15)
+    @ApiModelProperty(value = "数据源:0默认数据源,1其他数据源")
+    private java.lang.Integer type;
+}

+ 15 - 0
module_kzks/src/main/java/org/jeecg/modules/dataSourceSwitch/enums/DataSourceType.java

@@ -0,0 +1,15 @@
+package org.jeecg.modules.dataSourceSwitch.enums;
+
+public enum DataSourceType {
+
+    /**
+     * 主库
+     */
+    MASTER,
+
+    /**
+     * 从库
+     */
+    SLAVE
+
+}

+ 43 - 0
module_kzks/src/main/java/org/jeecg/modules/dataSourceSwitch/manage/DataSourceManagement.java

@@ -0,0 +1,43 @@
+package org.jeecg.modules.dataSourceSwitch.manage;
+
+import org.jeecg.modules.dataSourceSwitch.enums.DataSourceType;
+import org.springframework.context.annotation.Primary;
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import javax.sql.DataSource;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Primary
+@Component
+public class DataSourceManagement extends AbstractRoutingDataSource {
+
+    public static ThreadLocal<String> flag = new ThreadLocal<>();
+
+    @Resource
+    private DataSource master;
+
+    @Resource
+    private DataSource slave;
+
+    public DataSourceManagement(){
+        flag.set(DataSourceType.MASTER.name());
+    }
+
+    @Override
+    protected Object determineCurrentLookupKey() {
+        return flag.get();
+    }
+
+    @Override
+    public void afterPropertiesSet() {
+        Map<Object,Object> targetDataSource = new ConcurrentHashMap<>();
+        targetDataSource.put(DataSourceType.MASTER.name(),master);
+        targetDataSource.put(DataSourceType.SLAVE.name(),slave);
+        super.setTargetDataSources(targetDataSource);
+        super.setDefaultTargetDataSource(master);
+        super.afterPropertiesSet();
+    }
+}

+ 17 - 0
module_kzks/src/main/java/org/jeecg/modules/dataSourceSwitch/mapper/SwitchDataSourceMapper.java

@@ -0,0 +1,17 @@
+package org.jeecg.modules.dataSourceSwitch.mapper;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Param;
+import org.jeecg.modules.dataSourceSwitch.entity.SwitchDataSource;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * @Description: switch_data_source
+ * @Author: jeecg-boot
+ * @Date:   2023-08-27
+ * @Version: V1.0
+ */
+public interface SwitchDataSourceMapper extends BaseMapper<SwitchDataSource> {
+
+}

+ 5 - 0
module_kzks/src/main/java/org/jeecg/modules/dataSourceSwitch/mapper/xml/SwitchDataSourceMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.jeecg.modules.dataSourceSwitch.mapper.SwitchDataSourceMapper">
+
+</mapper>

+ 14 - 0
module_kzks/src/main/java/org/jeecg/modules/dataSourceSwitch/service/ISwitchDataSourceService.java

@@ -0,0 +1,14 @@
+package org.jeecg.modules.dataSourceSwitch.service;
+
+import org.jeecg.modules.dataSourceSwitch.entity.SwitchDataSource;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * @Description: switch_data_source
+ * @Author: jeecg-boot
+ * @Date:   2023-08-27
+ * @Version: V1.0
+ */
+public interface ISwitchDataSourceService extends IService<SwitchDataSource> {
+
+}

+ 19 - 0
module_kzks/src/main/java/org/jeecg/modules/dataSourceSwitch/service/impl/SwitchDataSourceServiceImpl.java

@@ -0,0 +1,19 @@
+package org.jeecg.modules.dataSourceSwitch.service.impl;
+
+import org.jeecg.modules.dataSourceSwitch.entity.SwitchDataSource;
+import org.jeecg.modules.dataSourceSwitch.mapper.SwitchDataSourceMapper;
+import org.jeecg.modules.dataSourceSwitch.service.ISwitchDataSourceService;
+import org.springframework.stereotype.Service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
+/**
+ * @Description: switch_data_source
+ * @Author: jeecg-boot
+ * @Date:   2023-08-27
+ * @Version: V1.0
+ */
+@Service
+public class SwitchDataSourceServiceImpl extends ServiceImpl<SwitchDataSourceMapper, SwitchDataSource> implements ISwitchDataSourceService {
+
+}