springboot hikari 多数据源 负载均衡 mysql

项目是gradle项目,build.gradle对应maven的pom.xml

build.gradle

dependencies {//类似于maven的dependencies
    implementation 'org.springframework.boot:spring-boot-starter-web'//spring web
    implementation 'org.springframework.boot:spring-boot-starter-jdbc'//jdbc
    runtimeClasspath 'mysql:mysql-connector-java'//mysql驱动
    implementation 'org.springframework.boot:spring-boot-starter-aop'//切面
    implementation 'org.springframework.boot:spring-boot-starter-data-redis'//redis
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2'//mybatis
}

application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    #Hikari连接池
    type: com.zaxxer.hikari.HikariDataSource
    mysql1:
      jdbc-url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
      username: x
      password: x
    mysql2:
      jdbc-url: jdbc:mysql://192.168.18.253:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
      username: x
      password: x

SpringbootApplication.java

排除数据源自动配置,改成手动配置

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})//排除数据源自动配置,改成手动配置
public class GradledemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(GradledemoApplication.class, args);
    }
}

HikariConfig.java

import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
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 org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class HikariConfig {
    /**
     * 配置别名
     */
    @Value("${mybatis.type-aliases-package}")
    private String typeAliasesPackage;

    /**
     * 配置mapper的扫描,找到所有的mapper.xml映射文件
     */
    @Value("${mybatis.mapper-locations}")
    private String mapperLocations;

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.mysql1")
    public HikariDataSource mysql1DataSource() {
        return new HikariDataSource();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.mysql2")
    public HikariDataSource mysql2DataSource() {
        return new HikariDataSource();
    }

    @Bean(name = "dynamicDataSource")
    @Primary
    public DynamicDataSource dataSource() {
        Map<Object, Object> targetDataSources = new HashMap<>(2);
        targetDataSources.put("mysql1", mysql1DataSource());
        targetDataSources.put("mysql2", mysql2DataSource());
        return new DynamicDataSource(mysql1DataSource(), targetDataSources);
    }

    /**
     * SqlSessionFactory 配置并放入容器中
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
        sqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
        return sqlSessionFactoryBean.getObject();
    }
}

DynamicDataSource.java

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Map;

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        this.setDefaultTargetDataSource(defaultTargetDataSource);
        this.setTargetDataSources(targetDataSources);
        this.afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceAspect.DATA_SOURCE_LIST.get((int) redisTemplate.opsForValue().get(DataSourceAspect.INDEX));
    }
}

DataSourceAspect.java

由切面去控制执行数据库操作时动态切换数据源
mysql1、mysql2对应application.yml的配置

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Aspect
@Order(1)
@Component
public class DataSourceAspect {
    public static final String INDEX = "index";
    public static final List<String> DATA_SOURCE_LIST = new ArrayList<String>(2) {{
        this.add("mysql1");
        this.add("mysql2");
    }};

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Around("execution(public * com.fu.gradledemo.mapper.*.*(..))")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        try {
            robin();//轮询数据库
            return point.proceed();
        } catch (MyBatisSystemException e) {
            robin();//连接不上就再轮询一次,获取另外一个mysql数据库连接
            return point.proceed();
        }
    }

    /**
     * 轮询mysql数据库
     */
    public void robin() {
        //没有key就创建key
        if (!redisTemplate.hasKey(INDEX)) {
            redisTemplate.opsForValue().set(INDEX, 0);
        } else {
            //有key就直接获取
            int getIndex = (int) redisTemplate.opsForValue().get(INDEX);
            //超过list集合的长度减一就重新赋值(轮询),利用redis单线程的特性存放全局index下标
            if (getIndex >= DATA_SOURCE_LIST.size() - 1) {
                redisTemplate.opsForValue().set(INDEX, 0);
            } else {
                redisTemplate.opsForValue().set(INDEX, ++getIndex);
            }
        }
    }
}

模拟是否成功动态切换数据源

localhost和253都创建demo数据库,user表里面的id一样,数据不一样,来确认数据是否真的动态切换。

localhost的demo库user表

在这里插入图片描述

253的demo库user表

name全部给它加个2
在这里插入图片描述
启动springboot项目。

第一次访问接口

在这里插入图片描述

第二次访问接口

在这里插入图片描述

题外

想要实现某些接口使用mysql1,某些接口使用mysql2。则使用aop切面+自定义注解的形式,只要加了自定义注解,就访问另外一个库,否则访问默认库。
数据不同步,则可以实现一主一从、互为主从的mysql。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot是一个非常流行的Java框架,它提供了很多方便的功能,包括数据管理。而HikariCP是一个高效的数据库连接池,它具有快速、稳定和可扩展性的优点。当我们需要在Spring Boot中使用多个数据时,可以选择使用HikariCP来管理这些数据。 首先,我们需要在pom.xml文件中引入HikariCP的依赖。然后,我们可以在application.properties或application.yml中配置多个数据。在这些配置中,我们需要为每个数据指定一个HikariCP连接池。例如: ``` spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/primary spring.datasource.primary.username=username spring.datasource.primary.password=password spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/secondary spring.datasource.secondary.username=username spring.datasource.secondary.password=password # HikariCP配置 spring.datasource.primary.hikari.maximum-pool-size=10 spring.datasource.secondary.hikari.maximum-pool-size=20 ``` 在这个配置中,我们定义了两个数据primary和secondary,并为它们每个指定了一个HikariCP连接池。我们还为每个连接池定义了一个最大连接数。 接下来,在我们的代码中,我们需要使用@Qualifier注解来注入正确的数据。例如: ``` @Autowired @Qualifier("primary") private DataSource primaryDataSource; @Autowired @Qualifier("secondary") private DataSource secondaryDataSource; ``` 在使用数据时,我们只需要在需要使用数据的地方使用正确的数据。例如: ``` @Repository public class PrimaryDao { private JdbcTemplate jdbcTemplate; @Autowired public void setDataSource(@Qualifier("primary") DataSource dataSource) { jdbcTemplate = new JdbcTemplate(dataSource); } // ... } @Repository public class SecondaryDao { private JdbcTemplate jdbcTemplate; @Autowired public void setDataSource(@Qualifier("secondary") DataSource dataSource) { jdbcTemplate = new JdbcTemplate(dataSource); } // ... } ``` 在这个例子中,我们定义了两个DAO,每个DAO都需要使用不同的数据。我们使用@Qualifier注解来注入正确的数据,然后在JdbcTemplate中使用该数据。 总的来说,使用Spring Boot和HikariCP管理多个数据非常简单,只需要配置不同的数据和连接池,然后注入正确的数据即可。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值