ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

springboot注解配置多数据源

2022-01-21 15:35:12  阅读:104  来源: 互联网

标签:springboot 数据源 springframework org import public 注解 name


在项目遇到多数据源的问题,主要是针对部分数据需要单独处理应用场景;

1.本次项目配置基于springboot+mybatis+maven集成的,首先在yml配置相关如下:其中需要注意单数据源是url,多数据源要改成 jdbc-url,否则会报异常(Error querying database.  Cause: java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName)

server:
  port: 8081

spring:
  datasource:
    database1:
      jdbc-url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
      username: root
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver
    database2:
      jdbc-url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf8
      username: root
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver

#mybatis config
mybatis:
  mapper-locations: classpath*:mapper/*/*.xml

  2.配置好了,需要在启动类先加上@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class})这个类位置:

import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
3.因为需要用到springboot的aop所以需要导包,在pom.xml文件导入
       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

 4.多数据源的结构以下:

 

 内容直接给大家展示:

1.DataSourceAspect
package com.example.demo.config.db.dataSource;
 

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
 
import java.lang.reflect.Method;
 
/**
 * 多数据源配置, 拦截器配置
 * @author lxp
 * @create 2021-12-28 12:15
 **/
@Aspect
@Component
@Slf4j
// 优先级, 1标识最先执行
@Order(1)
public class DataSourceAspect {
    @Pointcut("execution(* com.example.demo.mapper..*.*(..)))")
    public void dataSourcePoint() {}
 
    @Before("dataSourcePoint()")
    public void before(JoinPoint joinPoint) {
        Object target = joinPoint.getTarget();
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        // 执行方法名
        String methodName = methodSignature.getName();
        // 方法参数
        Class[] parameterTypes = methodSignature.getParameterTypes();
        try {
            // 获取方法, 直接getClass获取对象可能为代理对象
            Method method = target.getClass().getInterfaces()[0].getMethod(methodName, parameterTypes);
            // 添加默认数据源
            String dataSource = DataSourceType.Master.getName();
            if (null != method && method.isAnnotationPresent(MyDataSource.class)) {
                MyDataSource targetDataSource = method.getAnnotation(MyDataSource.class);
                dataSource = targetDataSource.value().getName();
            }
            // 此处添加线程对应的数据源到上下文
            // 在AbstractRoutingDataSource子类中拿到数据源, 加载后进行配置
            JdbcContextHolder.putDataSource(dataSource);
            log.info("generate data source : " + dataSource);
        } catch (Exception e) {
            log.info("error", e);
        }
 
    }
 
    /**
     * 清除数据源, 方法执行完成后, 清除数据源
     */
    @After("dataSourcePoint()")
    public void after(JoinPoint joinPoint) {
        JdbcContextHolder.clear();
    }
 
}

2.DataSourceConfig

package com.example.demo.config.db.dataSource;

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.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

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

/**
 * 数据源配置
 */
@Configuration
public class DataSourceConfig {

    @Bean(name =  "database1")
    @ConfigurationProperties(prefix = "spring.datasource.database1")
    public DataSource dataSource1() {
        //database1数据源
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "database2")
    @ConfigurationProperties(prefix = "spring.datasource.database2")
    public DataSource dataSource2() {
        //database2数据源
        return DataSourceBuilder.create().build();
    }
    
    @Bean(name="dynamicDataSource")
    @Primary    //优先使用,多数据源
    public DataSource dataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 设置默认数据源为first数据源
        dynamicDataSource.setDefaultTargetDataSource(dataSource1());
        // 配置多数据源,
        // 添加数据源标识和DataSource引用到目标源映射
        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put(DataSourceType.Master.getName(), dataSource1());
        dataSourceMap.put(DataSourceType.Slave.getName(), dataSource2());
        dynamicDataSource.setTargetDataSources(dataSourceMap);
        return dynamicDataSource;

    }
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

}

3.DataSourceType

package com.example.demo.config.db.dataSource;

public enum DataSourceType {

    Master("database1"),
    Slave("database2");
    private String name;
    private DataSourceType(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

4.DynamicDataSource

package com.example.demo.config.db.dataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;


public class DynamicDataSource extends AbstractRoutingDataSource {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @Override
    protected Object determineCurrentLookupKey() {
        logger.info("数据源为{}",JdbcContextHolder.getDataSource());
        return JdbcContextHolder.getDataSource();
    }
    
}
View Code

5.JdbcContextHolder

package com.example.demo.config.db.dataSource;
/**
 * 动态数据源的上下文 threadlocal
 */
public class JdbcContextHolder {
    
    private final static ThreadLocal<String> local = new ThreadLocal<>();
    
    public static void putDataSource(String name) {
        local.set(name);
    }
    
    public static String getDataSource() {
        return local.get();
    }
    /**
     * 清除数据源
     */
    public static void clear() {
        local.remove();
    }

}
View Code

6.MyDataSource

package com.example.demo.config.db.dataSource;

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

/**
 * 数据源选择--自定义注解
 */
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.METHOD) 
public @interface MyDataSource {

    DataSourceType value();    //默认主表
    
}
View Code

最后应用就比较简单了,默认情况有默认的数据库源,需要调用别的就加注解即可

 

 

 

最后通过调用接口可以看到数据是不同数据库的数据,完整的过程基本都有,多数据源要把dao层和xml文件隔离开更好的区分!!!

 

标签:springboot,数据源,springframework,org,import,public,注解,name
来源: https://www.cnblogs.com/lxp-java/p/15830392.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有