IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> spring-boot配置多数据源(动态数据源,基于注解和切面方式) -> 正文阅读

[Java知识库]spring-boot配置多数据源(动态数据源,基于注解和切面方式)

一、自定义DB注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DS {
    /**
     * 数据源名称
     */
    String value();

}

二、配置properties数据源

文件名:jdbc.properties

# slave-authserver
spring.datasource.slave.authserver.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.authserver.jdbc-url=jdbc:mysql://localhost:3306/smart-authserver?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
spring.datasource.slave.authserver.username=root
spring.datasource.slave.authserver.password=123456

# slave-data
spring.datasource.slave.data.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.data.jdbc-url=jdbc:mysql://localhost:3306/smart-data?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
spring.datasource.slave.data.username=root
spring.datasource.slave.data.password=123456

# slave-kpi
spring.datasource.slave.kpi.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.kpi.jdbc-url=jdbc:mysql://localhost:3306/smart-kpi?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
spring.datasource.slave.kpi.username=root
spring.datasource.slave.kpi.password=123456

# slave-logistics
spring.datasource.slave.logistics.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.logistics.jdbc-url=jdbc:mysql://localhost:3306/smart-logistics?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
spring.datasource.slave.logistics.username=root
spring.datasource.slave.logistics.password=123456

三、设置各数据源常量

public interface DataSourceConstants {

    /**
     * 从数据库-数据中心
     */
    String DS_KEY_SLAVE_DATA = "DS_KEY_SLAVE_DATA";

    /**
     * 从数据库-单点系统
     */
    String DS_KEY_SLAVE_AUTH = "DS_KEY_SLAVE_AUTH";

    /**
     * 从数据库-后勤系统
     */
    String DS_KEY_SLAVE_LOGISTICS = "DS_KEY_SLAVE_LOGISTICS";

    /**
     * 从数据库-考核系统
     */
    String DS_KEY_SLAVE_KPI = "DS_KEY_SLAVE_KPI";

}

四、Spring配置多数据源

import com.jnx.smart.authserver.db.DynamicDataSource;
import com.jnx.smart.base.constant.DataSourceConstants;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;

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

@Configuration
@PropertySource("classpath:jdbc.properties")
@MapperScan(basePackages = {
        "com.jnx.smart.authserver.business.repository.dao",
        "com.jnx.smart.data.business.repository.dao",
        "com.jnx.smart.assess.business.repository.dao",
        "com.jnx.smart.logistics.business.repository.dao"})
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class DynamicDataSourceConfig {

    @Bean
    @Primary
    public DataSource dynamicDataSource() {
        Map<Object, Object> dataSourceMap = new HashMap<>(2);
        dataSourceMap.put(DataSourceConstants.DS_KEY_SLAVE_AUTH, slaveDataSourceAuth());
        dataSourceMap.put(DataSourceConstants.DS_KEY_SLAVE_DATA, slaveDataSourceData());
        dataSourceMap.put(DataSourceConstants.DS_KEY_SLAVE_KPI, slaveDataSourceKpi());
        dataSourceMap.put(DataSourceConstants.DS_KEY_SLAVE_LOGISTICS, slaveDataSourceLogistics());
        //设置动态数据源
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(dataSourceMap);
        //单点登录系统,设置默认数据源为点点登陆数据库
        dynamicDataSource.setDefaultTargetDataSource(slaveDataSourceAuth());

        return dynamicDataSource;
    }

    /**
     * 主数据源-auth
     *
     * @return 后勤管理数据源bean
     */
    @Bean("DS_KEY_SLAVE_AUTH")
    @ConfigurationProperties(prefix = "spring.datasource.slave.authserver")
    public DataSource slaveDataSourceAuth() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 从数据源-data
     *
     * @return 文件系统数据源bean
     */
    @Bean("DS_KEY_SLAVE_DATA")
    @ConfigurationProperties(prefix = "spring.datasource.slave.data")
    public DataSource slaveDataSourceData() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 从数据源-kpi
     *
     * @return 文件系统数据源bean
     */
    @Bean("DS_KEY_SLAVE_KPI")
    @ConfigurationProperties(prefix = "spring.datasource.slave.kpi")
    public DataSource slaveDataSourceKpi() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 从数据源-logistics
     *
     * @return 文件系统数据源bean
     */
    @Bean("DS_KEY_SLAVE_LOGISTICS")
    @ConfigurationProperties(prefix = "spring.datasource.slave.logistics")
    public DataSource slaveDataSourceLogistics() {
        return DataSourceBuilder.create().build();
    }
}

五、数据源的上下文配置

数据源上下文设置

import com.jnx.smart.base.constant.DataSourceConstants;

/**
 * 动态数据源数据存储
 *
 * @author Joi
 */
public class DynamicDataSourceContextHolder {

    /**
     * 动态数据源名称上下文
     */
    private static final ThreadLocal<String> DATASOURCE_CONTEXT_KEY_HOLDER = new ThreadLocal<>();

    /**
     * 设置/切换数据源
     */
    public static void setContextKey(String key) {
        DATASOURCE_CONTEXT_KEY_HOLDER.set(key);
    }

    /**
     * 获取数据源名称
     */
    public static String getContextKey() {
        String key = DATASOURCE_CONTEXT_KEY_HOLDER.get();
        return key == null ? DataSourceConstants.DS_KEY_SLAVE_AUTH : key;
    }

    /**
     * 删除当前数据源名称
     */
    public static void removeContextKey() {
        DATASOURCE_CONTEXT_KEY_HOLDER.remove();
    }
}

获取上下文的数据源

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

/**
 * 动态数据源类
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    
    @Override
    protected Object determineCurrentLookupKey() {
        // 当设置数据源 key 到上下文,则从上下文中得到此数据源 key
        return DynamicDataSourceContextHolder.getContextKey();
    }
    
}

AOP切面处理

import com.jnx.smart.base.annotation.DS;
import org.aspectj.lang.ProceedingJoinPoint;
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.stereotype.Component;

import java.util.Objects;

/**
 * 动态数据源切面处理
 *
 * @author Joi
 */
@Aspect
@Component
public class DynamicDataSourceAspect {

    @Pointcut("@annotation(com.jnx.smart.base.annotation.DS)")
    public void dataSourcePointCut() {

    }

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        String dsKey = getDSAnnotation(joinPoint).value();
        DynamicDataSourceContextHolder.setContextKey(dsKey);
        try {
            return joinPoint.proceed();
        } finally {
            DynamicDataSourceContextHolder.removeContextKey();
        }
    }

    /**
     * 根据类或方法获取数据源注解
     */
    private DS getDSAnnotation(ProceedingJoinPoint joinPoint) {
        Class<?> targetClass = joinPoint.getTarget().getClass();
        DS dsAnnotation = targetClass.getAnnotation(DS.class);
        // 先判断类的注解,再判断方法注解
        if (Objects.nonNull(dsAnnotation)) {
            return dsAnnotation;
        } else {
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            return methodSignature.getMethod().getAnnotation(DS.class);
        }
    }

}

六、使用

在完成以上配置后,直接在需要使用的service方法上,打上注解任选一个需要的数据源@DB(value=DataSourceConstants.DS_KEY_SLAVE_DATA)
,程序执行时就会从指定的数据源进行操作。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-12 16:20:27  更:2022-05-12 16:22:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:21:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码