实战springboot整合mybatis-plus多数据源及手动切换数据源

建表语句

CREATE TABLE json_socket (
  id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
  note text COLLATE utf8mb4_bin NOT NULL COMMENT '发送数据',
  status int(1) NOT NULL DEFAULT '0' COMMENT '状态,1:已读,0:未读',
  create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (id) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC COMMENT='测试socket接受json信息';

application.yml

server:
  port: 8088

spring:
  datasource:
    druid:
      type: com.alibaba.druid.pool.DruidDataSource
      master:
        url: jdbc:mysql://127.0.0.1:3306/test_demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
      slave:
        url: jdbc:mysql://127.0.0.1:3306/wgcloud?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver

logging:
  config: classpath:logback-boot.xml
  level:
    root: info
    com.jinzheng.qhtime: info
mybatis-plus:
  type-aliases-package: com.testDynamicDa.entity
  mapper-locations: classpath:mapper/*.xml
#  configuration:
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.5</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springboot-dynamic-datasource</artifactId>
<properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- aop 切面 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>


        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.8</version>
        </dependency>
        <!--主从配置依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>2.4.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>
        <!--mybatis-plus生成器-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>

        <!-- 模板引擎 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.0</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.14</version>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.6.9</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.24</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!--validation-api-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>com.jayway.jsonpath</groupId>
            <artifactId>json-path</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>6.0.0</version>
        </dependency>
    </dependencies>

</project>

启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * 启动服务
 */
@SpringBootApplication
@EnableAsync
@EnableScheduling   // 开启定时任务
public class DigitalServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(DigitalServerApplication.class, args);
    }
}

注解类

package com.testDynamicDa.annocation;
import com.testDynamicDa.constant.CommonConstant;
import java.lang.annotation.*;

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSourceType {
    /**
     * 切换数据源名称
     */
    public String value() default CommonConstant.MASTER;
}

工具类

package com.testDynamicDa.commont;
import com.alibaba.druid.pool.DruidDataSource;
import com.testDynamicDa.constant.CommonConstant;
import com.testDynamicDa.annocation.DataSourceType;
import com.testDynamicDa.config.DruidConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.*;

@Aspect
@Component
@Slf4j
public class DataSourceAspect {

    // 设置DataSource注解的切点表达式
//    @Pointcut("@annotation(com.liubujun.config.aespect.DataSourceType)")
    @Pointcut("execution(public * com.testDynamicDa.service..*.*(..))")
    public void dynamicDataSourcePointCut(){

    }

    //环绕通知
    @Around("dynamicDataSourcePointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        DataSourceType defineAnnotation = getDefineAnnotation(joinPoint);
        String key = "";
        //判断方法上是否有注解,没有注解则默认是走的是主服务器
        if (defineAnnotation == null ) {
            key = CommonConstant.MASTER;
        }else {
            key = defineAnnotation.value();
        }
        //判断数据库是否断开连接
        key = getConnection(key);
        DynamicDataSourceHolder.setDynamicDataSourceKey(key);
        Object proceed = null;
        try {
            proceed =  joinPoint.proceed();
        } finally {
            DynamicDataSourceHolder.removeDynamicDataSourceKey();
        }
        return proceed;
    }

    /**
     * 先判断方法的注解,后判断类的注解,以方法的注解为准
     * @param joinPoint
     * @return
     */
    private DataSourceType getDefineAnnotation(ProceedingJoinPoint joinPoint){
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        DataSourceType dataSourceAnnotation = methodSignature.getMethod().getAnnotation(DataSourceType.class);
        if (Objects.nonNull(methodSignature)) {
            return dataSourceAnnotation;
        } else {
            Class<?> dsClass = joinPoint.getTarget().getClass();
            return dsClass.getAnnotation(DataSourceType.class);
        }
    }

    /**
     * 判断数据库是否连接成功
     * @return
     */
    private String getConnection(String target) throws SQLException {
        //将数据源名称添加到list集合,方便后续操作
        List<String> dataSources = new ArrayList<>();
        dataSources.add(CommonConstant.SLAVE);
        dataSources.add(CommonConstant.MASTER);
        //获取装配好的bean对象
        DruidConfig druidConfig = (DruidConfig)SpringUtil.getBean("druidConfig");
        DruidDataSource druidDataSource = new DruidDataSource();
        if(StringUtils.isBlank(target)){
            druidDataSource = (DruidDataSource) druidConfig.masterDataSource();
        }else if (target.equals(CommonConstant.SLAVE)) {
            druidDataSource = (DruidDataSource) druidConfig.slaveDataSource();
        }else if (target.equals(CommonConstant.MASTER)) {
            druidDataSource = (DruidDataSource) druidConfig.masterDataSource();
        }else{
            return target;
        }
        try {
            Connection connection = DriverManager.getConnection(druidDataSource.getUrl(), druidDataSource.getUsername(), druidDataSource.getPassword());
            log.info("连接db:"+connection.getCatalog().trim());
        } catch (SQLException e) {
            dataSources.remove(target);
            // shuffle 打乱顺序
            Collections.shuffle(dataSources);
            String changeTarget = dataSources.get(0);
            getConnection(changeTarget);
            log.info("========================数据源:{}连接异常,切换数据源为:{}===========================",target,changeTarget);
            return changeTarget;
        }
        return target;
    }

}
package com.testDynamicDa.commont;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import java.util.Map;

/**
 * 动态数据源
 * 调用AddDefineDataSource组件的addDefineDynamicDataSource()方法,获取原来targetdatasources的map,并将新的数据源信息添加到map中,并替换targetdatasources中的map
 * 切换数据源时可以使用@DataSource(value = "数据源名称"),或者DynamicDataSourceContextHolder.setContextKey("数据源名称")
 * @author zhangyu
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DynamicDataSource extends AbstractRoutingDataSource {

    //备份所有数据源信息,
    private Map<Object, Object> defineTargetDataSources;

    /**
     * 决定当前线程使用哪个数据源
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceHolder.getDynamicDataSourceKey();
    }

}
package com.testDynamicDa.commont;
import com.testDynamicDa.constant.CommonConstant;
import lombok.extern.slf4j.Slf4j;

/**
 * 数据源切换处理
 */
@Slf4j
public class DynamicDataSourceHolder {
    /**
     * 保存动态数据源名称
     */
    private static final ThreadLocal<String> DYNAMIC_DATASOURCE_KEY = new ThreadLocal<>();

    /**
     * 设置/切换数据源,决定当前线程使用哪个数据源
     */
    public static void setDynamicDataSourceKey(String key){
        log.info("数据源切换为:{}",key);
        DYNAMIC_DATASOURCE_KEY.set(key);
    }

    /**
     * 获取动态数据源名称,默认使用mater数据源
     */
    public static String getDynamicDataSourceKey(){
        String key = DYNAMIC_DATASOURCE_KEY.get();
        return key == null ? CommonConstant.MASTER : key;
    }

    /**
     * 移除当前数据源
     */
    public static void removeDynamicDataSourceKey(){
        log.info("移除数据源:{}",DYNAMIC_DATASOURCE_KEY.get());
        DYNAMIC_DATASOURCE_KEY.remove();
    }
}

package com.testDynamicDa.commont;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if(SpringUtil.applicationContext == null) {
            SpringUtil.applicationContext = applicationContext;
        }
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    //根据类名获取指定对象
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }
    //根据类型获取指定对象
    public static <T> T getBean(Class<T> clazz){
        return getApplicationContext().getBean(clazz);
    }
    //根据类名和类型获取指定对象
    public static <T> T getBean(String name,Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }
}

配置类

package com.testDynamicDa.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.testDynamicDa.constant.CommonConstant;
import com.testDynamicDa.commont.DynamicDataSource;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Data
@Configuration
public class DruidConfig {

    @Bean(name = CommonConstant.MASTER)
    @ConfigurationProperties("spring.datasource.druid.master")
    public DataSource masterDataSource()
    {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return dataSource;
    }

    @Bean(name = CommonConstant.SLAVE)
    @ConfigurationProperties("spring.datasource.druid.slave")
    public DataSource slaveDataSource()
    {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return dataSource;
    }

    @Bean
    @Primary
    public DynamicDataSource dynamicDataSource() {
        Map<Object, Object> dataSourceMap = new HashMap<>(2);
        dataSourceMap.put(CommonConstant.MASTER,masterDataSource());
        dataSourceMap.put(CommonConstant.SLAVE,slaveDataSource());
        //设置动态数据源
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setDefaultTargetDataSource(masterDataSource());
        dynamicDataSource.setTargetDataSources(dataSourceMap);
        //将数据源信息备份在defineTargetDataSources中
        dynamicDataSource.setDefineTargetDataSources(dataSourceMap);
        return dynamicDataSource;
    }
}

package com.testDynamicDa.config;
import com.testDynamicDa.exception.ErrorException;
import com.testDynamicDa.util.CommonResult;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常捕捉
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ErrorException.class)
    ResponseEntity errorException(ErrorException err){
        CommonResult<Object> objectCommonResult = CommonResult.failed(err.getMessage());
        if("401".compareTo(String.valueOf(err.getCode()))==0){
            return new ResponseEntity<>(objectCommonResult, HttpStatus.UNAUTHORIZED);
        }else if("403".compareTo(String.valueOf(err.getCode()))==0){
            return new ResponseEntity<>(objectCommonResult, HttpStatus.FORBIDDEN);
        }else {
            return new ResponseEntity<>(objectCommonResult, HttpStatus.BAD_REQUEST);
        }
    }

}

package com.testDynamicDa.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.Connector;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @CLassName GracefulShutdownTomcat
 **/
@Component
@Slf4j
public class GracefulShutdownTomcat implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {

    private volatile Connector connector;
    private final int waitTime = 30;

    @Override
    public void customize(Connector connector) {
        this.connector = connector;
    }

    @Override
    public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
        if (connector == null) {
            return;
        }
        this.connector.pause();
        Executor executor = this.connector.getProtocolHandler().getExecutor();
        if (executor instanceof ThreadPoolExecutor) {
            try {
                ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
                threadPoolExecutor.shutdown();
                if (!threadPoolExecutor.awaitTermination(waitTime, TimeUnit.SECONDS)) {
                    log.warn("Tomcat thread pool did not shut down gracefully within " + waitTime
                            + " seconds. Proceeding with forceful shutdown");
                }
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    }
}


package com.testDynamicDa.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * @Description MyBatis配置
 **/
@Configuration
@EnableTransactionManagement
@MapperScan("com.testDynamicDa.mapper")
public class MyBatisConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

package com.testDynamicDa.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

/**
 * 配置线程池
 */
@Configuration
public class SpringAsyncConfig {

    @Bean("MyExecutorTime")//这里我指定了线程池的名称
    public Executor asyncServiceExecutor(){
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        //设核心线程
        threadPoolTaskExecutor.setCorePoolSize(2);
        //最大线程数
        threadPoolTaskExecutor.setMaxPoolSize(6);
        //缓冲队列大小
        threadPoolTaskExecutor.setQueueCapacity(5);
        //等待任务在关机时完成--表明等待所有线程执行完
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        //等待时间
        threadPoolTaskExecutor.setAwaitTerminationSeconds(60);
        //拒绝策略走默认
        //线程名称前缀
        threadPoolTaskExecutor.setThreadNamePrefix("myAsync-time-");
        // 初始化线程
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

}

package com.testDynamicDa.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @CLassName TomcatConfig
 **/
@Configuration
public class TomcatConfig {

    @Autowired
    private GracefulShutdownTomcat gracefulShutdownTomcat;

    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addConnectorCustomizers(gracefulShutdownTomcat);
        return tomcat;
    }
}

常量类

package com.testDynamicDa.constant;

public class CommonConstant {
    /**
     * 默认数据源标识
     */
    public static final String MASTER = "master";
    /**
     * 从数据源标识
     */
    public static final String SLAVE = "slave";
}

实体类

package com.testDynamicDa.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * socket用户实体类
 */
@Data
@ApiModel(value = "JsonSocket对象", description = "socket接受json信息")
public class JsonSocket implements Serializable {

    private static final long serialVersionUID = 5390393587976656442L;

    @ApiModelProperty(value = "编号")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @ApiModelProperty(value = "发送数据")
    @TableField("note")
    private String note;

    @ApiModelProperty(value = "状态,1:已读0:未读")
    @TableField("status")
    private Integer status;

    @ApiModelProperty(value = "创建时间")
    @TableField("create_time")
    private LocalDateTime createTime;
}

异常类

package com.testDynamicDa.exception;

/**
 * 异常捕捉
 */
public class ErrorException extends RuntimeException {
    protected String errorCode;
    protected int code;

    public ErrorException(int code, String message) {
        super(message);
        this.code = code;
    }

    public ErrorException(int code, String errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
        this.code = code;
    }

    public int getCode() {
        return this.code;
    }

    public String getErrorCode() {
        return this.errorCode;
    }
}

mapper

package com.testDynamicDa.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.testDynamicDa.entity.JsonSocket;

/**
 * socket服务接受信息
 */

public interface JsonSocketMapper extends BaseMapper<JsonSocket> {


}

业务逻辑类

package com.testDynamicDa.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.testDynamicDa.entity.JsonSocket;

import java.util.List;

public interface JsonSocketService extends IService<JsonSocket> {

    List<JsonSocket> getList();

    List<JsonSocket> getLists(String dbType);

}

package com.testDynamicDa.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.testDynamicDa.annocation.DataSourceType;
import com.testDynamicDa.commont.DynamicDataSourceHolder;
import com.testDynamicDa.entity.JsonSocket;
import com.testDynamicDa.mapper.JsonSocketMapper;
import com.testDynamicDa.service.JsonSocketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
@Slf4j

public class JsonSocketServiceImpl extends ServiceImpl<JsonSocketMapper, JsonSocket> implements JsonSocketService {


    @DataSourceType("slave")
    @Override
    public List<JsonSocket> getList() {
        return this.baseMapper.selectList(null);
    }

    @Override
    public List<JsonSocket> getLists(String dbType) {
        DynamicDataSourceHolder.setDynamicDataSourceKey(dbType);
        List<JsonSocket> jsonSockets = this.baseMapper.selectList(null);
        return jsonSockets;
    }
}

控制类

package com.testDynamicDa.controller;

import com.testDynamicDa.service.JsonSocketService;
import com.testDynamicDa.util.CommonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("jsonSocket")
public class JsonSocketController {

    @Autowired
    private JsonSocketService jsonSocketService;

    /**
     * http://localhost:8088/jsonSocket/getList
     * 接口方法上加@DataSourceType("slave")
     * @return
     */
    @GetMapping("/getList")
    public CommonResult getList(){
        return CommonResult.success(jsonSocketService.getList(),"接口方法上加@DataSourceType(\"slave\")");
    }

    /**
     * http://localhost:8088/jsonSocket/getLists
     * mybasits-plus自带方法
     * @return
     */
    @GetMapping("/getLists")
    public CommonResult getLists(){
        return CommonResult.success(jsonSocketService.list(),"mybasits-plus自带方法");
    }

    /**
     * http://localhost:8088/jsonSocket/getListss
     *  手动切库
     * @return
     */
    @GetMapping("/getListss")
    public CommonResult getListss(@RequestParam(defaultValue = "slave") String dbType){
        return CommonResult.success(jsonSocketService.getLists(dbType),"手动切库");
    }

}


xml

<?xml version="1.0" encoding="UF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.testDynamicDa.mapper.JsonSocketMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.testDynamicDa.entity.JsonSocket">
        <id column="id" property="id" />
        <result column="note" property="note" />
        <result column="status" property="status" />
        <result column="create_time" property="createTime" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, note, status, create_time
    </sql>

</mapper>

结果展示
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot是一个高效的Java开发框架,它能够方便开发者集成MyBatis-Plus实现多数据源的动态切换以及支持分页查询。MyBatis-Plus是一种优秀的ORM框架,它增强了MyBatis的基础功能,并支持通过注解方式进行映射。 首先,我们需要在pom.xml文件中添加MyBatis-Plus和数据库连接池的依赖。在application.yml文件中,我们需要配置多个数据源和对应的连接信息。我们可以定义一个DataSourceConfig用于获取多个数据源,然后在Mapper配置类中使用@MapperScan(basePackages = {"com.test.mapper"})来扫描Mapper接口。 要实现动态切换数据源,我们可以自定义一个注解@DataSource来标注Mapper接口或方法,然后使用AOP拦截数据源切换,实现动态切换。在实现分页查询时,我们可以使用MyBatis-Plus提供的分页插件来支持分页查询。 代码示例: 1. 在pom.xml文件中添加MyBatis-Plus和数据库连接池的依赖。 ``` <dependencies> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.4</version> </dependency> </dependencies> ``` 2. 在application.yml文件中配置多个数据源和对应的连接信息。以两个数据源为例: ``` spring: datasource: druid: db1: url: jdbc:mysql://localhost:3306/db1 username: root password: root driver-class-name: com.mysql.jdbc.Driver db2: url: jdbc:mysql://localhost:3306/db2 username: root password: root driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource # 指定默认数据源 primary: db1 ``` 3. 定义一个DataSourceConfig用于获取多个数据源。 ``` @Configuration public class DataSourceConfig { @Bean("db1") @ConfigurationProperties("spring.datasource.druid.db1") public DataSource dataSource1() { return DruidDataSourceBuilder.create().build(); } @Bean("db2") @ConfigurationProperties("spring.datasource.druid.db2") public DataSource dataSource2() { return DruidDataSourceBuilder.create().build(); } @Bean @Primary public DataSource dataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(); // 设置数据源映射关系 Map<Object, Object> dataSourceMap = new HashMap<>(); dataSourceMap.put("db1", dataSource1()); dataSourceMap.put("db2", dataSource2()); dynamicDataSource.setTargetDataSources(dataSourceMap); // 设置默认数据源 dynamicDataSource.setDefaultTargetDataSource(dataSource1()); return dynamicDataSource; } } ``` 4. 在Mapper配置类中使用@MapperScan(basePackages = {"com.test.mapper"})来扫描Mapper接口,并使用@DataSource注解来标注Mapper接口或方法。 ``` @Configuration @MapperScan(basePackages = {"com.test.mapper"}) public class MybatisPlusConfig { @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } } @DataSource("db1") public interface UserMapper { @Select("select * from user where id = #{id}") User selectById(@Param("id") Long id); } ``` 5. 实现AOP拦截数据源切换。 ``` @Aspect @Component public class DataSourceAspect { @Before("@annotation(ds)") public void beforeSwitchDataSource(JoinPoint point, DataSource ds) { String dataSource = ds.value(); if (!DynamicDataSourceContextHolder.containDataSourceKey(dataSource)) { System.err.println("数据源 " + dataSource + " 不存在,使用默认数据源"); } else { System.out.println("使用数据源:" + dataSource); DynamicDataSourceContextHolder.setDataSourceKey(dataSource); } } } ``` 6. 分页查询的使用示例: ``` @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override @DataSource("db1") public IPage<User> getUserList(int pageNum, int pageSize) { Page<User> page = new Page<>(pageNum, pageSize); return userMapper.selectPage(page, null); } } ``` 以上就是SpringBoot整合MyBatis-Plus实现多数据源的动态切换和分页查询的具体实现过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值