springboot实现多数据源配置(Druid/Hikari)

这篇具有很好参考价值的文章主要介绍了springboot实现多数据源配置(Druid/Hikari)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

使用springboot+mybatis-plus+(Druid/Hikari)实现多数据源配置

操作步骤:
  1. 引入相应的maven坐标
  2. 编写mybatis配置,集成mybatis或mybatis-plus(如果已集成可跳过)
  3. 编写数据源配置类
  4. 编写注解,并通过aop进行增强(编写数据源切换代码)
  5. 类或方法中使用注解,对数据源进行切换

第一步:引入需要相应maven坐标

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

        <!-- aop注解实现aspectjweaver依赖 -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>
        <!-- mysql-plus 依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.0</version>
        </dependency>
        <!-- Mysql驱动包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--阿里数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.14</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

第二步:编写mybatis-plus配置集成

server:
  port: 8000

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    master:
      url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
      username: root
      password: 123456
    slaver:
      # 从数据源开关/默认关闭
      enabled: false
      url: jdbc:mysql://localhost:3306/slave?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
      username: root
      password: 123456
    druid:
      # 初始连接数
      initial-size: 5
      # 最小连接池数量
      min-idle: 10
      # 最大连接池数量
      max-active: 20
      # 获取连接等待超时时间
      max-wait: 60000
mybatis-plus:
  mapper-locations: classpath*:mapper/*Mapper.xml

logging:
  level:
    com.example.demo: debug


以下是集成mp相关的代码,不需要可直接跳过!!!(以user表为例)

userMapper

package com.example.demo.datesource.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.datesource.domain.User;

import java.util.List;

public interface UserService extends IService<User> {

    List<User> getUserList();
    List<User> getUserListByXml();

    List<User> testSlave();
}

userMapper.xml

<?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="com.example.demo.datesource.mapper.UserMapper">


    <select id="getUserListByXml" resultType="com.example.demo.datesource.domain.User">
        select * from user
    </select>
</mapper>

userService

package com.example.demo.datesource.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.datesource.domain.User;

import java.util.List;

public interface UserService extends IService<User> {

    List<User> getUserList();
    List<User> getUserListByXml();

    List<User> testSlave();
}

userServiceImpl

package com.example.demo.datesource.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.datesource.annotation.UseDataSource;
import com.example.demo.datesource.domain.User;
import com.example.demo.datesource.enums.DataSourceType;
import com.example.demo.datesource.mapper.UserMapper;
import com.example.demo.datesource.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<User> getUserList() {
        return list();
    }

    @Override
    public List<User> getUserListByXml(){
        return userMapper.getUserListByXml();
    }

    @Override
    public List<User> testSlave() {
        return list();
    }
}

User

package com.example.demo.datesource.domain;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("user")
public class User {

    @TableId
    private Long id;

    private String name;

    private String sex;

    private int age;
}

mybatis-plus 集成完毕!

第三步:编写数据源的配置类(例:Druid、Hikari)

一、@ConfigurationProperties要和配置文件中的配置对应上
(1)Druid:
package com.example.demo.datesource.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.example.demo.datesource.config.properties.DruidPropertiesConfig;
import com.example.demo.datesource.datasource.DynamicDataSource;
import com.example.demo.datesource.enums.DataSourceType;
import com.example.demo.datesource.utils.SpringUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
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 javax.swing.*;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class DruidConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.master")
    public DataSource masterDataSource(DruidPropertiesConfig propertiesConfig){
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return propertiesConfig.setDataSourceProperties(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.slaver")
    @ConditionalOnProperty(prefix = "spring.datasource.slaver", name = "enabled", havingValue = "true")
    public DataSource slaverDataSource(DruidPropertiesConfig propertiesConfig){
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return propertiesConfig.setDataSourceProperties(dataSource);
    }

    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSource masterDataSource){
        Map<Object,Object> targetDataSource = new HashMap<>();
        targetDataSource.put(DataSourceType.MASTER.name(),masterDataSource);
        setDataSource(targetDataSource,DataSourceType.SLAVE.name(),"slaverDataSource");
        return new DynamicDataSource(masterDataSource,targetDataSource);
    }

    public void setDataSource(Map<Object,Object> targetDataSource,String sourceName,String beanName){
        try {
            DataSource dataSource = SpringUtils.getBean(beanName);
            targetDataSource.put(sourceName,dataSource);
        }catch (Exception e){

        }
    }

}

增加DruidPropertiesConfig类,用于给数据源配置上配置文件对应的属性

package com.example.demo.datesource.config.properties;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DruidPropertiesConfig {

    @Value("${spring.datasource.druid.initial-size}")
    private int initialSize;

    @Value("${spring.datasource.druid.min-idle}")
    private int minIdle;

    @Value("${spring.datasource.druid.max-active}")
    private int maxActive;

    @Value("${spring.datasource.druid.max-wait}")
    private int maxWait;

    public DruidDataSource setDataSourceProperties(DruidDataSource dataSource){
        dataSource.setInitialSize(this.initialSize);
        dataSource.setMinIdle(this.minIdle);
        dataSource.setMaxActive(this.maxActive);
        dataSource.setMaxWait(this.maxWait);
        return dataSource;
    }

}

(2)Hikari:配置上基本和druid相同,只需把配置类改为如下且配置文件的“url”改为“jdbc-url”即可

springboot多数据源druid,Java,spring boot,mybatis,java
springboot多数据源druid,Java,spring boot,mybatis,java

二、增加SpringUtils类,用于读取spring中的bean
package com.example.demo.datesource.utils;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class SpringUtils implements BeanFactoryPostProcessor {

    private static ConfigurableListableBeanFactory beanFactory;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        SpringUtils.beanFactory = configurableListableBeanFactory;
    }


    public static <T> T getBean(String name){
        return (T) beanFactory.getBean(name);
    }


}

三、添加DynamicDataSource类

(1)此类是用来配置动态数据源的关键。该类继承spring的抽象类AbstractRoutingDataSource,通过这个类可以实现动态数据源切换。其中维护着默认数据源(defaultTargetDataSource)和数据源列表(targetDataSources),通过afterPropertiesSet()方法对数据源列表进行解析以及设置数据源。
程序每次对数据库发起连接时,都会访问到AbstractRoutingDataSource的getConnection()方法,此方法会调用determineCurrentLookupKey的相应实现,此处实现为获取线程变量。

package com.example.demo.datesource.datasource;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

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

public class DynamicDataSource extends AbstractRoutingDataSource {

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

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSourceType();
    }
}

(2)添加DynamicDataSourceContextHolder类,此类用于切换数据源,根据ThreadLocal做多线程数据隔离,每一次切换都能保证不影响其他线程的正常运行

package com.example.demo.datesource.datasource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DynamicDataSourceContextHolder {

    public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);

    private static final ThreadLocal<String> CONTEXT_HOLDER =  new ThreadLocal<>();

    /**
     * 设置数据源的变量
     */
    public static void setDataSourceType(String dsType){
        log.info("切换到{}数据源",dsType);
        CONTEXT_HOLDER.set(dsType);
    }


    /**
     * 获得数据源的变量
     */
    public static String getDataSourceType()
    {
        return CONTEXT_HOLDER.get();
    }

    /**
     * 清空数据源变量,此方法可调动gc对线程进行清除
     */
    public static void clearDataSourceType()
    {
        CONTEXT_HOLDER.remove();
    }

}

AbstractRoutingDataSource切换线程变量来切换数据源源码。
此处就是获取之前在DynamicDataSourceContextHolder中set到线程中的数据源名,通过数据源名获取维护的数据源列表中对应的数据源

springboot多数据源druid,Java,spring boot,mybatis,java

第四步:使用

大致思路:定义一个切换数据源注解,通过注解aop的形式对数据源进行切换,在类或方法中使用注解,设置对应的数据源名称以此来达到数据源切换

一、定义一个切换数据源注解
package com.example.demo.datesource.annotation;

import com.example.demo.datesource.enums.DataSourceType;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

    public DataSourceType dataSource() default DataSourceType.MASTER;

}

二、编写aop代码

@within:此注解可以作用于类中的所有方法,如果@UseDataSource放到类上,此类下的所有的方法都会被当做切点拦截
@Order(1):提升组件注册到spring中的优先级
point.proceed():原来执行的程序,也就是原请求,想要做环绕增强就再这周围写就可以了

package com.example.demo.datesource.aspectj;

import com.example.demo.datesource.annotation.UseDataSource;
import com.example.demo.datesource.datasource.DynamicDataSourceContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.Objects;

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

    @Pointcut("@annotation(com.example.demo.datesource.annotation.UseDataSource) || @within(com.example.demo.datesource.annotation.UseDataSource)")
    public void pointCut(){}

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable{
        UseDataSource useDataSource = getDataSource(point);
        if(Objects.nonNull(useDataSource)){
            DynamicDataSourceContextHolder.setDataSourceType(useDataSource.dataSource().name());
        }
        try {
            return point.proceed();
        }finally {
            //清空threadlocalMap的entry。避免内存泄漏
            DynamicDataSourceContextHolder.clearDataSourceType();
        }

    }

    public UseDataSource getDataSource(ProceedingJoinPoint point){
        MethodSignature signature = (MethodSignature) point.getSignature();
        UseDataSource annotation = AnnotationUtils.findAnnotation(signature.getMethod(), UseDataSource.class);
        if(Objects.nonNull(annotation)){
            return annotation;
        }
        return AnnotationUtils.findAnnotation(signature.getDeclaringType(),UseDataSource.class);
    }

}

三、编写注解到类或方法上

springboot多数据源druid,Java,spring boot,mybatis,java

运行结果:
springboot多数据源druid,Java,spring boot,mybatis,java
springboot多数据源druid,Java,spring boot,mybatis,java
springboot多数据源druid,Java,spring boot,mybatis,java
springboot多数据源druid,Java,spring boot,mybatis,java

至此,数据源切换成功!!!

另外,如果需要增加新的数据源需要的操作:
1、启动配置文件中增加新的数据源参数
2、数据源配置类中,新增配置源bean,并且把数据源set到targetDataSource中
3、DataSourceType枚举类中,添加新数据源的枚举
如图所示:
springboot多数据源druid,Java,spring boot,mybatis,java

springboot多数据源druid,Java,spring boot,mybatis,java
springboot多数据源druid,Java,spring boot,mybatis,java
springboot多数据源druid,Java,spring boot,mybatis,java文章来源地址https://www.toymoban.com/news/detail-635538.html

到了这里,关于springboot实现多数据源配置(Druid/Hikari)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot配置自定义数据源(Druid德鲁伊)的步骤。

    今天和大家分享下在Springboot中配置自定义数据源Druid的两种方法及步骤。 方法一: 1.在pom.xml配置依赖(注释里面的内容) 2.配置自己的数据源设置,我是在yaml文件中配置的,顺便提醒一下,在配置yaml文件的时候缩进问题一定要注意,不然无法读取到就会报错。 spring: datasourc

    2024年02月15日
    浏览(58)
  • SpringBoot整合(五)HikariCP、Druid数据库连接池—多数据源配置

    在项目中,数据库连接池基本是必不可少的组件。在目前数据库连接池的选型中,主要是 Druid ,为 监控 而生的数据库连接池。 HikariCP ,号称 性能 最好的数据库连接池。 在Spring Boot 2.X 版本,默认采用 HikariCP 连接池。而阿里大规模采用 Druid 。下面介绍在SpringBoot中使用Hika

    2024年02月17日
    浏览(79)
  • SpringBoot整合Mybatis-Plus、Druid配置多数据源

    目录 1.初始化项目 1.1.初始化工程 1.2.添加依赖 1.3.配置yml文件 1.4.Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹 1.5.配置使用数据源 1.5.1.注解方式 1.5.2.基于AOP手动实现多数据源原生的方式 2.结果展示 Mybatis-Plus:简介 | MyBatis-Plus (baomidou.com) 在正式开始之前,先初始

    2024年02月11日
    浏览(48)
  • Dynamic DataSource 多数据源配置【 Springboot + DataSource + MyBatis Plus + Druid】

    MybatisPlus多数据源配置主要解决的是多数据库连接和切换的问题。在一些大型应用中,由于数据量的增长或者业务模块的增多,可能需要访问多个数据库。这时,就需要配置多个数据源。 2.1.1、引用依赖 2.1.2、application.yml 配置 2.1.3、通用配置类 2.1.4、使用方式 这里便不过多的

    2024年02月03日
    浏览(48)
  • SpringBoot整合Mybatis-Plus+Druid实现多数据源

    🌺本文主要讲解 springboot +mybatisplus + druid 实现多数据源配置功能 🌺 主页传送门:📀 传送 Spring Boot:    Spring Boot是一个基于Spring框架的开源Java开发框架,旨在简化Spring应用程序的开发、配置和部署。它提供了一种快速、敏捷的方式来构建独立的、生产级别的Spring应用程

    2024年02月09日
    浏览(104)
  • SpringBoot数据源——为什么平时默认线程池是Hikari

    本文主要对DataSourceAutoConfiguration类进行讲解,然后对这个类的注解做一个解释,所以直接打开这个类,开始看…… ps:我用的版本是2.3.0.RELEASE 目录 DataSourceAutoConfiguration类注解 @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }) @ConditionalOnMis

    2024年02月06日
    浏览(55)
  • JAVA:Springboot动态装配Druid多数据源

    1、简介 最近打算搭建一个鉴权中心服务,采用springboot+FastMybatis装配Druid,考虑后续拓展采用Druid多数据源配置,以一个数据源为主,多个动态数据源为辅的结构。除了数据库,后续会结合shiro安全框架来搭建。 2、引用 在pom.xml添加框架Springboot +FastMybatis + Druid相关maven引用。

    2024年02月09日
    浏览(48)
  • Druid监控 + 多数据源配置

    先贴一下用的依赖项。 yaml配置文件的配置。 负责读取yaml文件的数据源配置,生成数据源。还有创建动态数据源容器。另外ServletRegistrationBean 和 FilterRegistrationBean的配置和生成。 就是我们的动态数据源,负责继承和初始化 AbstractRoutingDataSource。还有就是重写determineCurrentLookupKe

    2024年01月22日
    浏览(64)
  • SpringBoot3整合Druid数据源的解决方案

    druid-spring-boot-3-starter目前最新版本是1.2.20,虽然适配了SpringBoot3,但缺少自动装配的配置文件,会导致加载时报加载驱动异常。 需要手动在resources目录下创建 META-INF/spring/ 目录,并且在 META-INF/spring/ 创建 org.springframework.boot.autoconfigure.AutoConfiguration.imports , 文件中添加如下内容

    2024年03月09日
    浏览(106)
  • [前车之鉴] SpringBoot原生使用Hikari数据连接池升级到动态多数据源的深坑解决方案 & RocketMQ吞掉异常问题排查

    当前业务场景我们使用原生SpringBoot整合Hikari数据源连接池提供服务,但是近期业务迭代需要使用动态多数据源,很自然想到dynamic-source,结果一系列惨案离奇发生。。。 原生SpringBoot整合HikariCp数据源连接池配置【这个是没问题的配置】 而升级后的动态多数据源配置如下:【

    2024年02月01日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包