springboot 2.0 整合druid+ mybatisPlus 动态多数据源

springboot这个框架,相信现在大部分企业都是使用的该框架,但是2.0 之后与之前的版本还是有些区别。这里我们谈谈如何整合mybatisPlus多数据源

一 、首先父模块pom.xml



    4.0.0

    com.silankeji
    framework
    1.0-RELEASE
    pom
    framework
    www.silankeji.cn

    
        mybaitsplus
        swagger
        redis
        commons
    

    
        2.1.1.RELEASE
        5.1.3.RELEASE
        8.0.13
        1.2.47
        2.6
        2.3
        1.1.10
        2.0.3.RELEASE
        3.8.1
        3.8.0
        2.9.2
        2.9.0
    
    
    
        
            
            
                org.springframework.boot
                spring-boot-dependencies
                ${spring.boot.version}
                pom
                import
            
            
            
                com.silankeji
                mybaitsplus
                ${project.version}
            
            
            
                com.silankeji
                swagger
                ${project.version}
            
            
            
                com.silankeji
                redis
                ${project.version}
            
            
            
                com.silankeji
                commons
                ${project.version}
            
        
    

    
    
        
        
            com.alibaba
            fastjson
            ${fastJson.version}
        
        
        
            commons-lang
            commons-lang
            ${common.version}
        
        
            org.apache.commons
            commons-lang3
            ${common.lang3.version}
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.boot
            spring-boot-autoconfigure
        
        
        
            org.springframework.boot
            spring-boot-starter-aop
        

        
        
            org.springframework.boot
            spring-boot-starter-logging
        
        
        
            org.springframework.boot
            spring-boot-devtools
            ${devtool.version}
            runtime
        
        
        
            org.springframework.boot
            spring-boot-starter-test
        
        
        
            org.springframework.boot
            spring-boot-configuration-processor
        
        
        
            org.springframework
            spring-core
            ${spring.version}
        
        
            org.springframework
            spring-context
            ${spring.version}
        
        
            org.springframework
            spring-beans
            ${spring.version}
        
    

    
    
        
            releases
            http://自己的maven私服/repository/maven-releases
        
        
            snapshots
            http://自己的maven私服/repository/maven-snapshots
        
    

    
        
            
            
                org.apache.maven.plugins
                maven-compiler-plugin
                ${maven.compiler.version}
                
                    1.8
                    1.8
                    UTF-8
                
            
        
    



二、mybatis模块 pom.xml引入依赖jar包

这里我是父模块管理jar包版本,此处可以自己引用相关版本



    
        framework
        com.silankeji
        1.0-RELEASE
        ../pom.xml
    
    4.0.0
    mybaitsplus
    jar
    mybatisplus
    http://maven.apache.org

    
        
        
            mysql
            mysql-connector-java
            ${mysql.version}
        
        
        
            org.springframework.boot
            spring-boot-starter-jdbc
        
        
        
            com.baomidou
             mybatis-plus-boot-starter
            ${mybatis.version}
            
                
                    org.springframework.boot
                    spring-boot-starter-jdbc
                
                
                    org.springframework.boot
                    spring-boot-autoconfigure
                
            
        

        
        
            com.alibaba
            druid-spring-boot-starter
            ${druid.version}
        
        
        
            com.silankeji
            commons
            1.0-RELEASE
        
    

    
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                ${maven.compiler.version}
                
                    1.8
                    1.8
                    utf-8
                
            
        
    


三、定义DataSource 注解

自定义多数据源切换的注解,默认为主库

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {

    String value() default "master";
}

四、配置文件

这里需要配置druid以及mybatisplus的config配置文件
MybatisPlusConfig.java

@Configuration("mybatisPlusConfig")
@MapperScan(basePackages = "com.silankeji.**.mapper", sqlSessionTemplateRef = "sqlSessionTemplate")
public class MybatisPlusConfig {

    /**
     * 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        //开启PageHelper
        paginationInterceptor.setLocalPage(true);
        return paginationInterceptor;
    }

    /**
     * sql执行效率插件
     * 只在dev和test环境生效
     */
    @Bean
    @Profile({"dev", "test"})
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        //sql执行的最大时间1秒
        performanceInterceptor.setMaxTime(1000);
        //是否格式化
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }

    @Bean("master")
    @ConfigurationProperties(prefix = "spring.datasource.druid.master")
    @Primary
    public DataSource master() {
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * 动态数据源
     */
    @Bean(name = "dynamic")
    public DataSource multipleDataSource(@Qualifier("master") DataSource master) {
        //设置默认数据源
        DynamicDataSource.getInstance().setDefaultTargetDataSource(master);
        DataSourceMap.getDataSourceMap().put("master", master);
        DynamicDataSource.getInstance().setTargetDataSources(DataSourceMap.getDataSourceMap());
        return DynamicDataSource.getInstance();
    }

    @Bean(name = "transactionManager")
    @Order
    public DataSourceTransactionManager transactionManager(@Qualifier("dynamic") DataSource dataSource) {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        //这里进行动态数据源重新设置
        DynamicDataSource.getInstance().setTargetDataSources(DataSourceMap.getDataSourceMap());
        //注入resolvedDataSources中
        DynamicDataSource.getInstance().afterPropertiesSet();
        return transactionManager;
    }

    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamic") DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCacheEnabled(false);
        sqlSessionFactory.setConfiguration(configuration);
        sqlSessionFactory.setPlugins(new Interceptor[]{
                //添加分页功能
                paginationInterceptor()
        });
        return sqlSessionFactory.getObject();
    }

    @Bean(name = "sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier(value = "sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
        return sqlSessionTemplate;
    }

}

DruidConfig.java
这里设置了默认用户以及密码可以取消

@Configuration
@ConditionalOnProperty(name = "druid.config.enable",havingValue = "true")
public class DruidConfig{

    @Resource
    private Environment environment;

    private final Map paramMap = new HashMap<>(7);

    @Bean
    public ServletRegistrationBean startViewServlet() {
        getDruidConfigProperties();
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        //Ip白名单,多个在value中用逗号隔开,不配置默认所有
        servletRegistrationBean.addInitParameter("allow", paramMap.get("allow"));
        //ip 黑名单,这里黑名单优先级大于白名单
        servletRegistrationBean.addInitParameter("deny", paramMap.get("deny"));
        //控制台管理
        servletRegistrationBean.addInitParameter("loginUsername", paramMap.get("loginUsername"));
        servletRegistrationBean.addInitParameter("loginPassword", paramMap.get("loginPassword"));
        //是否可以点击页面的重置按钮
        servletRegistrationBean.addInitParameter("resetEnable", paramMap.get("resetEnable"));
        return servletRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean statFilter() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        //添加过滤规则
        filterRegistrationBean.addUrlPatterns(paramMap.get("urlPatterns"));
        //忽略过滤的格式
        filterRegistrationBean.addInitParameter("exclusions", paramMap.get("exclusions"));
        return filterRegistrationBean;
    }

    private void getDruidConfigProperties(){
        if(StringUtils.isEmpty(environment.getProperty("druid.config.allow"))){
            paramMap.put("allow","");
        }else{
            paramMap.put("allow",environment.getProperty("druid.config.allow"));
        }

        if(StringUtils.isEmpty(environment.getProperty("druid.config.deny"))){
            paramMap.put("deny","");
        }else{
            paramMap.put("deny",environment.getProperty("druid.config.deny"));
        }

        if(StringUtils.isEmpty(environment.getProperty("druid.config.loginUsername"))){
            paramMap.put("loginUsername","admin");
        }else{
            paramMap.put("loginUsername",environment.getProperty("druid.config.loginUsername"));
        }

        if(StringUtils.isEmpty(environment.getProperty("druid.config.loginPassword"))){
            paramMap.put("loginPassword","admin123");
        }else{
            paramMap.put("loginPassword",environment.getProperty("druid.config.loginPassword"));
        }

        if(StringUtils.isEmpty(environment.getProperty("druid.config.resetEnable"))){
            paramMap.put("resetEnable","false");
        }else{
            paramMap.put("resetEnable",environment.getProperty("druid.config.resetEnable"));
        }

        if(StringUtils.isEmpty(environment.getProperty("druid.config.urlPatterns"))){
            paramMap.put("urlPatterns","/*");
        }else{
            paramMap.put("urlPatterns",environment.getProperty("druid.config.urlPatterns"));
        }

        if(StringUtils.isEmpty(environment.getProperty("druid.config.exclusions"))){
            paramMap.put("exclusions","*.js,*.gif,*.jpg,*.png ,*.css,*.ico,/druid/*");
        }else{
            paramMap.put("exclusions",environment.getProperty("druid.config.exclusions"));
        }
    }

}

配置动态多数据源路由对象
DynamicDataSource.java

public class DynamicDataSource extends AbstractRoutingDataSource {

    private static volatile DynamicDataSource dynamicDataSource;

    private DynamicDataSource(){}



    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDatasource();
    }

    /**
     * 单例获取对象
     * @return DynamicDataSource
     */
    public static DynamicDataSource getInstance() {
        if (dynamicDataSource == null) {
            synchronized (DynamicDataSource.class) {
                if (dynamicDataSource == null) {
                    dynamicDataSource = new DynamicDataSource();
                }
            }
        }
        return dynamicDataSource;
    }

}

配置多数据源上下文
DataSourceContextHolder.java

public class DataSourceContextHolder {

    private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal();

    public static void setDataSource(String name){
        CONTEXT_HOLDER.set(name);
    }

    public static String getDatasource(){
        return CONTEXT_HOLDER.get();
    }

    public static void cleanDataSource(){
        CONTEXT_HOLDER.remove();
    }
}

配置数据源存储容器
DataSourceMap.java

 public final class DataSourceMap {

    /**
     * 全局静态存放数据源名称Map
     */
    private static final Map DATASOURCEMAP = new HashMap<>();


    private DataSourceMap(){
    }

    /**
     * 获取数据源集合
     * @return
     */
    public static Map getDataSourceMap(){
        return DATASOURCEMAP;
    }

    /**
     * 添加数据源bean进入集合中
     * @param dataSourceBeanName
     * @return
     */
    public static boolean setDataSourceBeanName(String dataSourceBeanName, DataSource dataSource){
        if(StringUtils.isBlank(dataSourceBeanName)||dataSource == null){
            return false;
        }
       return DATASOURCEMAP.put(dataSourceBeanName,dataSource)!=null;

    }

    /**
     * 删除集合中的某个数据源
     * @param dataSourceBeanName
     * @return
     */
    public static boolean remove(String dataSourceBeanName){
        if(StringUtils.isBlank(dataSourceBeanName)){
            return false;
        }
        return DATASOURCEMAP.remove(dataSourceBeanName)==null;
    }

}

五、数据源动态切面设置

切记要优先加载
DataSourceAspect.java

@Component
@Aspect
@Order(-1)
public class DataSourceAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceAspect.class);

    @Pointcut("@within(com.silankeji.mybatisplus.annotations.DataSource) || @annotation(com.silankeji.mybatisplus.annotations.DataSource)")
    public void pointCut(){

    }

    @Before("pointCut() && @annotation(dataSource)")
    public void doBefore(DataSource dataSource){
        LOGGER.info("选择数据源---"+dataSource.value());
        DataSourceContextHolder.setDataSource(dataSource.value());
    }

    @After("pointCut()")
    public void doAfter(){
        DataSourceContextHolder.cleanDataSource();
    }
}

六、客户端的使用

1.引入jar包


            com.silankeji
            mybaitsplus
            1.0-RELEASE
        
        
            com.silankeji
            swagger
            1.0-RELEASE
        
        
            com.silankeji
            commons
            1.0-RELEASE
        
        
            com.silankeji
            redis
            1.0-RELEASE
        

2.属性配置

#mybatisPlus 配置
mybatis-plus:
  #xml 路径
  mapper-locations: classpath*:mybatis/*.xml
  global-config:
  # 全局编码
    id-type: 3
    #逻辑删除
    logic-delete-value: 1
    #逻辑不删除
    logic-not-delete-value: 0
    #对应数据库字段下划线转java驼峰命名
    db-column-underline: true
  configuration:
    # map 键值转驼峰
    map-underscore-to-camel-case: true
#swagger2配置
swagger2:
  enable: true
  title: frameDemo
  basePack: com.silankeji.demo2.controller

#druid 配置
spring:
  redis:
    enable: true
  datasource:
    druid:
      #开启com.silankeji.mybatisplus 数据源配置信息
      enable: true
      master:
        #数据源配置 wall表示防火墙
        filters: stat,wall,log4j2
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://数据库地址:3306/master?useUnicode=true&characterEncoding=UTF-8&allowMutiqueries=true
        username: root
        password: root123
        #初始线程数,最小活跃线程,最大活跃线程
        initial-size: 1
        min-idle: 1
        max-active: 5
        # 连接等待时间单位毫秒
        max-wait: 60000
        #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
        time-between-eviction-runs-millis: 60000
        #配置一个连接在池中最小生存的时间,单位是毫秒
        min-evictable-idle-time-millis: 300000
        validation-query: SELECT 1 FROM DUAL
        #\u6307\u660E\u8FDE\u63A5\u662F\u5426\u88AB\u7A7A\u95F2\u8FDE\u63A5\u56DE\u6536\u5668\uFF0C\u8FDB\u884C\u6821\u9A8C\uFF0C\u6821\u9A8C\u5931\u8D25\u5219\uFF0C\u6B64\u8FDE\u63A5\u4ECE\u6C60\u4E2D\u5220\u9664
        test-while-idle: true
        #\u501F\u51FA\u8FDE\u63A5\u65E0\u9700\u6D4B\u8BD5
        test-on-borrow: false
        test-on-return: false
        #打开PSCache,并且指定每个连接上PSCache的大小
        pool-prepared-statements: false
        #\u4E0Eoracle\u6570\u636E\u5E93\u6709\u5173
        max-pool-prepared-statement-per-connection-size: 20
        #\u6253\u5F00mergeSql\u529F\u80FD\uFF0C\u6162Sql\u8BB0\u5F55
        connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      slaver:
        #\u914D\u7F6E\u76D1\u63A7\u7EDF\u8BA1\u62E6\u622A\u7684filters\uFF0Cwall\u7528\u4E8E\u9632\u706B\u5899
        filters: stat,wall,log4j2
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://数据库地址:3306/slaver?useUnicode=true&characterEncoding=UTF-8&allowMutiqueries=true
        username: root
        password: root123
        #\u521D\u59CB\u5316\u5927\u5C0F\uFF0C\u6700\u5C0F\u8FDE\u63A5\uFF0C\u6700\u5927\u8FDE\u63A5
        initial-size: 1
        min-idle: 1
        max-active: 5
        #\u83B7\u53D6\u8FDE\u63A5\u7B49\u5F85\u8D85\u65F6\u65F6\u95F4
        max-wait: 60000
        #\u914D\u7F6E\u95F4\u9694\u591A\u4E45\u8FDB\u884C\u4E00\u6B21\u68C0\u67E5\uFF0C\u9700\u8981\u5173\u95ED\u7684\u7A7A\u95F2\u8FDE\u63A5
        time-between-eviction-runs-millis: 60000
        #\u914D\u7F6E\u4E00\u4E2A\u8FDE\u63A5\u5728\u6C60\u4E2D\u7684\u6700\u5C0F\u751F\u5B58\u65F6\u95F4
        min-evictable-idle-time-millis: 300000
        validation-query: SELECT 1 FROM DUAL
        #\u6307\u660E\u8FDE\u63A5\u662F\u5426\u88AB\u7A7A\u95F2\u8FDE\u63A5\u56DE\u6536\u5668\uFF0C\u8FDB\u884C\u6821\u9A8C\uFF0C\u6821\u9A8C\u5931\u8D25\u5219\uFF0C\u6B64\u8FDE\u63A5\u4ECE\u6C60\u4E2D\u5220\u9664
        test-while-idle: true
        #\u501F\u51FA\u8FDE\u63A5\u65E0\u9700\u6D4B\u8BD5
        test-on-borrow: false
        test-on-return: false
        #\u6253\u5F00psCache \u5E76\u6307\u5B9A\u6BCF\u4E2ApsCache\u5927\u5C0F\uFF0Coracle\u4E3Atrue mysql\u4E3Afalse\uFF0C\u5206\u5E93\u5206\u8868\u8F83\u591A\u8BBE\u7F6Efalse
        pool-prepared-statements: false
        #\u4E0Eoracle\u6570\u636E\u5E93\u6709\u5173
        max-pool-prepared-statement-per-connection-size: 20
         #通过connectProperties属性来打开mergeSql功能;慢SQL记录
        connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      slaver1:
        #数据源配置 wall表示防火墙
        filters: stat,wall,log4j2
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://数据库地址:3306/slaver1?useUnicode=true&characterEncoding=UTF-8&allowMutiqueries=true
        username: root
        password: root123
        #初始线程数,最小活跃线程,最大活跃线程
        initial-size: 1
        min-idle: 1
        max-active: 5
        # 连接等待时间单位毫秒
        max-wait: 60000
        #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
        time-between-eviction-runs-millis: 60000
        #配置一个连接在池中最小生存的时间,单位是毫秒
        min-evictable-idle-time-millis: 300000
        validation-query: SELECT 1 FROM DUAL
        #\u6307\u660E\u8FDE\u63A5\u662F\u5426\u88AB\u7A7A\u95F2\u8FDE\u63A5\u56DE\u6536\u5668\uFF0C\u8FDB\u884C\u6821\u9A8C\uFF0C\u6821\u9A8C\u5931\u8D25\u5219\uFF0C\u6B64\u8FDE\u63A5\u4ECE\u6C60\u4E2D\u5220\u9664
        test-while-idle: true
        #\u501F\u51FA\u8FDE\u63A5\u65E0\u9700\u6D4B\u8BD5
        test-on-borrow: false
        test-on-return: false
        #打开PSCache,并且指定每个连接上PSCache的大小
        pool-prepared-statements: false
        #\u4E0Eoracle\u6570\u636E\u5E93\u6709\u5173
        max-pool-prepared-statement-per-connection-size: 20
        #\u6253\u5F00mergeSql\u529F\u80FD\uFF0C\u6162Sql\u8BB0\u5F55
        connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
#druid页面配置
druid:
  config:
    #是否开启druid监控com.silankeji.mybatisplus
    enable: true
    #白名单 默认所有可访问
    allow: 127.0.0.1
    #黑名单 默认为空
    deny: 118.25.23.12
    #账号 默认admin
    loginUsername: root
    #密码 默认admin123
    loginPassword: root123
    #是否允许点击页面的重置按钮,默认false
    resetEnable: false
    #过滤url 默认 /*
    urlPatterns: /*
    #不过滤的资源,注意*打头必须加双引号,下面值为默认值
    exclusions: "*.js,*.gif,*.jpg,*.png ,*.css,*.ico,/druid/*"
  1. 动态数据源配置
    MultiDataSource.java
@Configuration
public class MultiDataSource{

    @Bean("slaver")
    @ConfigurationProperties(prefix = "spring.datasource.druid.slaver")
    public DataSource slaver() {
        //创建数据源
        DataSource dataSource = DruidDataSourceBuilder.create().build();
        //将数据源放入动态池
        DataSourceMap.setDataSourceBeanName("slaver",dataSource);
       return dataSource;
    }

    @Bean("zzz")
    @ConfigurationProperties(prefix = "spring.datasource.druid.slaver1")
    public DataSource slaver1() {
        //创建数据源
        DataSource dataSource = DruidDataSourceBuilder.create().build();
        //将数据源放入动态池
        DataSourceMap.setDataSourceBeanName("zzz",dataSource);
        return dataSource;
    }
}

4.代码中使用,这里有3个数据源只需要使用注解@DataSource就可以使用不同的数据源

@RestController
@Api(value = "操作员工相关相信Controller")
public class EmployeeController {

    private static final Logger LOG = LoggerFactory.getLogger(EmployeeController.class);

    @Resource
    private EmployeeService employeeService;

    @RequestMapping(value = "/queryEmployee/{empNo}",method=RequestMethod.POST)
    @ApiOperation(value = "获取员工信息",notes = "根据员工编号查询员工相关信息",httpMethod = "POST",produces = "application/json")
    @ApiImplicitParam(name = "empNo",value = "员工编号如:1,2...",required = true,dataType="string",paramType = "path")
    @DataSource
    public BaseResponse getEmployeeInfo(@PathVariable(name = "empNo") String employeeNumber){
        LOG.info("begin query employee info by employeeNumber:{}",employeeNumber);
        EntityWrapper wrapper = new EntityWrapper<>();
        wrapper.eq("employeeNumber",employeeNumber);
        BaseResponse response = new BaseResponse();
        response.setResult(employeeService.selectOne(wrapper));
        LOG.info("query employee info is{}",JSON.toJSONString(response));
        return response;
    }

    @RequestMapping(value = "/addEmployee",method = RequestMethod.POST)
    @ApiOperation(value = "添加员工信息",notes ="增加员工相关信息",httpMethod = "POST",produces = "application/json",consumes = "application/json")
    @DataSource("zzz")
    public BaseResponse addEmployeeInfo(@RequestBody @ApiParam(name = "employee",value = "员工信息类") Employee employee){
        LOG.info("begin add employee info:{}",JSON.toJSONString(employee));
        BaseResponse response = new BaseResponse();
        response.setResult(employeeService.insert(employee));
        LOG.info("add employee info is {}",JSON.toJSONString(response));
        return response;
    }

    @RequestMapping(value = "/modifyEmployee",method = RequestMethod.POST)
    @ApiOperation(value = "修改员工信息",notes ="编辑员工相关信息",httpMethod = "POST",produces = "application/json",consumes = "application/json")
    @DataSource("slaver")
    public BaseResponse modifyEmployeeInfo(@RequestBody @ApiParam(name = "employee",value = "员工信息类") Employee employee){
        LOG.info("begin update employee info:{}",JSON.toJSONString(employee));
        BaseResponse response = new BaseResponse();
        response.setResult(employeeService.update(employee,new EntityWrapper().eq("employeeNumber",employee.getEmployeeNumber())));
        LOG.info("update employee info is {}",JSON.toJSONString(response));
        return response;
    }
}

你可能感兴趣的:(springboot 2.0 整合druid+ mybatisPlus 动态多数据源)