springboot和nacos整合mybatis-plus实现多数据源管理

时间:2023-01-27 14:52:24


写了一个小demo,通过mybatis-plus实现多数据源管理
使用了mysql和redis两类数据库。
Mybatis-Plus官网
Mybatis-Plus的多数据源Dynamic-Datasource

1.依赖

springboot版本 2.3.12.RELEASE
springcloud版本 2.2.8.RELEASE
nacos版本 2.1.0
nacos安装部署教程
springboot整合nacos

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</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>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-autoconfigure</artifactId>
            <version>2.2.2</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
    </dependencies>

2.配置文件

项目中的 bootstrap.yaml文件

spring:
  application:
    name: springboot-muldata
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        namespace: config
        file-extension: yaml
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
    bootstrap:
      enabled: true

nacos中的配置文件
填写自己的数据库,用户名,密码

server:
    port: 8503

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false 
      datasource:
        master: 
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/blog-demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
          username: root
          password: mysql
        mysql_2:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/study?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
          username: root
          password: mysql
        redis:
          database: 1
          host: 127.0.0.1
          port: 6379
          username: root
          password:

#打印sql语句
#因为用了mybatis-plus组件,就不用写mybatis
mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true  # 开启驼峰命名
  type-aliases-package: com.example.springbootmuldatasources.entity
  mapper-locations: classpath*:mappers/*.xml

3.redis测试

3.1redis配置文件

RedisConfiguration文件

    public GenericObjectPoolConfig poolConfig(){
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        //控制一个pool可分配多少个jedis实例
        poolConfig.setMaxTotal(500);
        //最大空闲数
        poolConfig.setMaxIdle(200);
        //每次释放连接的最大数目,默认是3
        poolConfig.setNumTestsPerEvictionRun(1024);
        //逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
        poolConfig.setTimeBetweenEvictionRunsMillis(30000);
        //连接的最小空闲时间 默认1800000毫秒(30分钟)
        poolConfig.setMinEvictableIdleTimeMillis(-1);
        poolConfig.setSoftMinEvictableIdleTimeMillis(10000);
        //最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
        poolConfig.setMaxWaitMillis(1500);
        poolConfig.setTestOnBorrow(true);
        poolConfig.setTestWhileIdle(true);
        poolConfig.setTestOnReturn(false);
        poolConfig.setJmxEnabled(true);
        poolConfig.setBlockWhenExhausted(false);
        return poolConfig;
    }


    @Bean
    public LettuceConnectionFactory lettuceConnectionFactory() {
        LettucePoolingClientConfiguration lettucePoolingClientConfiguration = LettucePoolingClientConfiguration.builder()
                .poolConfig(poolConfig())
                .build();
        // 单机redis
        RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
        redisConfig.setHostName("127.0.0.1");
        redisConfig.setPort(6379);
        redisConfig.setDatabase(0);


        // 哨兵redis
        //RedisSentinelConfiguration redisConfig = new RedisSentinelConfiguration();

        // 集群redis
//        RedisClusterConfiguration redisConfig = new RedisClusterConfiguration();
//        Set<RedisNode> nodeses = new HashSet<>();
//        String[] hostses = nodes.split("-");
//        for (String h : hostses) {
//            h = h.replaceAll("\\s", "").replaceAll("\n", "");
//            if (!"".equals(h)) {
//                String host = h.split(":")[0];
//                int port = Integer.valueOf(h.split(":")[1]);
//                nodeses.add(new RedisNode(host, port));
//            }
//        }
//        redisConfig.setClusterNodes(nodeses);
//        // 跨集群执行命令时要遵循的最大重定向数量
//        redisConfig.setMaxRedirects(3);
//        redisConfig.setPassword(password);

        return new LettuceConnectionFactory(redisConfig, lettucePoolingClientConfiguration);
    }
}

3.2controller

@RestController
@RequestMapping("/redis")
public class RedisTestController {
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * redis存入String类型数据的测试
     * @return
     */
    @GetMapping("/testString")
    public String RedisTestString(){
//        设置String的key,value
        redisTemplate.opsForValue().set("testString","String");
//        获取redis存储的string类型的value
        String testString = (String) redisTemplate.opsForValue().get("testString");
        return testString;

    }
    /**
     * redis存入hash类型数据的测试
     * @return
     */
    @GetMapping("/testHash")
    public Map<String,String> RedisTestHash(){
        HashMap<String, String> stringStringHashMap = new HashMap<>();

        stringStringHashMap.put("testHash1","HashValue1");
        stringStringHashMap.put("testHash2","HashValue2");
        stringStringHashMap.put("testHash3","HashValue3");
        stringStringHashMap.put("testHash4","HashValue4");
        //单个存入
        redisTemplate.opsForHash().put("testHash","testHash0","HashValue0");
        // 设置redis的hash的key,value
        redisTemplate.opsForHash().putAll("testHash",stringStringHashMap);
        // //获得redis存储的Hash
        System.out.println("输出redis存储的Hash");

        Object o = redisTemplate.opsForHash().get("testHash", "testHash0");
        System.out.println(o);
        Map result = redisTemplate.opsForHash().entries("testHash");
        System.out.println(result);
        return result;
    }

    /**
     * redis存入list类型数据的测试
     * @return String
     */
    @GetMapping("/testList")
    public String RedisTestList(){
        ArrayList<String> stringList = new ArrayList<>();
        stringList.add("list1");
        stringList.add("list2");
        stringList.add("list3");
        // 设置redis的list的key,value,使用json的形式
        String key = "testList1";
        redisTemplate.opsForValue().set(key,stringList.toString());
        //输出redis存储的list
        System.out.println("输出redis存储的testList1");
        String result = (String) redisTemplate.opsForValue().get(key);
        System.out.println(result);
        ArrayList<String> stringList2 = new ArrayList<>();
        stringList2.add("list4");
        stringList2.add("list5");
        stringList2.add("list6");
        String key2 = "testList2";
        redisTemplate.opsForList().rightPush(key2,stringList2);
        //去除list的数据
        Object result2 = redisTemplate.opsForList().rightPop(key2);
        //取出后数据内就没有了,redis里面就不会有数据所以重新存入
        redisTemplate.opsForList().rightPush(key2,stringList2);
        System.out.println("输出redis存储的testList2");
        System.out.println(result2);
        return result+result2;

    }

    /**
     * redis存入Set类型数据的测试
     * @return
     */
    @GetMapping("/testSet")
    public String  RedisTestSet(){
        String key = "testSet";
        Long add = redisTemplate.opsForSet().add(key, "set1", "set2", "set3", "set4");
        System.out.println(add);
        Object pop = redisTemplate.opsForSet().pop(key);
        System.out.println(pop);
        String result = pop.toString();
        return result;
    }
}

3.3测试

http://localhost:8503/redis/testHash
springboot和nacos整合mybatis-plus实现多数据源管理

4.mysql测试

4.1数据库表和结构

/*
 Navicat Premium Data Transfer

 Source Server         : hhf-test
 Source Server Type    : MySQL
 Source Server Version : 80019
 Source Host           : localhost:3306
 Source Schema         : blog-demo

 Target Server Type    : MySQL
 Target Server Version : 80019
 File Encoding         : 65001

 Date: 26/01/2023 14:55:53
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for dog
-- ----------------------------
DROP TABLE IF EXISTS `dog`;
CREATE TABLE `dog`  (
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `age` int NULL DEFAULT NULL,
  `gender` enum('MALE','FEMALE') CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT 'MALE',
  PRIMARY KEY (`name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of dog
-- ----------------------------
INSERT INTO `dog` VALUES ('小花', 6, 'MALE');
INSERT INTO `dog` VALUES ('小黄', 10, 'FEMALE');

SET FOREIGN_KEY_CHECKS = 1;

4.2实体类和枚举

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dog {
    private String name;
    private Integer age;
    private Gender gender;
}
public enum Gender {
    MALE,FEMALE
}

4.3DogMapper.xml

<mapper namespace="com.example.springbootmuldatasources.mapper.DogMapper">
    <select id="selectByName" resultType="com.example.springbootmuldatasources.entity.Dog">
        select * from dog where name = #{name}
    </select>
</mapper>

4.4DogMapper

@Mapper
public interface DogMapper {
    //@Select("select * from dog where name = #{name}")
    Dog selectByName(String name);
}

4.5service和serviceImpl

service

@Service
public interface DogService {
    Dog getByName(String name);
}

serviceImpl

@Service
public class DogServiceImpl implements DogService {
    @Autowired
    private DogMapper dogMapper;
    @Override
    public Dog getByName(String name) {
        Dog dog = dogMapper.selectByName(name);
        return dog;
    }
}

4.6controller

@RestController
@RequestMapping("/mysql")
public class MysqlController {
    @Autowired
    private DogService dogService;

    @GetMapping("/getDogName")
    public void getOne(){
        Dog dog = dogService.getByName("小花");
        System.out.println(dog);
    }
}

4.7测试

http://localhost:8503/mysql/getDogName
springboot和nacos整合mybatis-plus实现多数据源管理