springboot+mybatis +yml文件配置多數據源


記錄一下java開發中多數據源的配置過程,

參考博客:https://blog.csdn.net/weinichendian/article/details/72903757,我在這里進行了整理,使用yml;排除了里邊在springboot2.0報錯的內容,以及里邊沒有說太清楚的內容,進行了詳細的說明

1.配置文件application.yml

   personnel:#數據源1
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3307/person?useSSL=false&useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&allowMultiQueries=true&allowPublicKeyRetrieval=true
      username: root
      password: *******
    userauth:#數據源2
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3307/user?useSSL=false&useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&allowMultiQueries=true&allowPublicKeyRetrieval=true
      username: root
      password: ******

2.不同數據源枚舉:

public enum DataSourceEnum {master,slaver;}

3.枚舉類工具 set

public class DataSourceContextHolder {
    private static final ThreadLocal<DataSourceEnum> CONTEXT_HOLDER = new ThreadLocal<DataSourceEnum>() {
 
        @Override
        protected DataSourceEnum initialValue() {
            return DataSourceEnum.master;
        }
    };
    public static void setDataSourceType(DataSourceEnum type) {
        CONTEXT_HOLDER.set(type);
    }
    public static DataSourceEnum getDataSourceType() {
        return CONTEXT_HOLDER.get();
    }
    public static void resetDataSourceType() {
        CONTEXT_HOLDER.set(DataSourceEnum.master);
    }
}

4.自定義注解

@Retention(RetentionPolicy.RUNTIME) // 在運行時可見
@Target(ElementType.METHOD) // 注解可以用在方法上
public @interface DataSourceTypeAnno { //使用方式在service層方法上添加@DataSourceTypeAnno(DataSourceEnum.數據源枚舉類型)用於指定所使用的數據源
DataSourceEnum value() default DataSourceEnum.master; }

5.aop攔截:這里使用asp的

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.core.annotation.Order;
import org.springframework.stereotype.Component;
 
import java.lang.reflect.Method;
 

@Component
@Aspect
@Order(-100)//為了保證可以攔截到
public class DataSourceAspect {
    @Pointcut("execution(* com.yzy.*.*..*(..)) " +     //這里掃描的切點包是主要是service層,根據service層方法的上邊所說的的自定義注解,去判斷所使用的數據源類型,並動態切換數據源
            "&& @annotation(com.yzy.config.DataSourceTypeAnno)")
    public void dataSourcePointcut() {
    }
 
    @Around("dataSourcePointcut()")
    public Object doAround(ProceedingJoinPoint pjp) {
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        Method method = methodSignature.getMethod();
        DataSourceTypeAnno typeAnno = method.getAnnotation(DataSourceTypeAnno.class);
        DataSourceEnum sourceEnum = typeAnno.value();
 
        if (sourceEnum == DataSourceEnum.master) {
            DataSourceContextHolder.setDataSourceType(DataSourceEnum.master);
        } else if (sourceEnum == DataSourceEnum.slaver) {
            DataSourceContextHolder.setDataSourceType(DataSourceEnum.slaver);
        }
 
        Object result = null;
        try {
            result = pjp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        } finally {
            DataSourceContextHolder.resetDataSourceType();
        }
 
        return result;
    }
}

6.繼承 AbstractRoutingDataSource 類,實現對應數據源key的切換

package com.yzy.config;
 
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource { protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }

7.配置mybatisConfig=》數據源信息

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;//org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;該包在springboot2.0被取代,目前網上的都是這個springboot1.5的包,所以會一直報錯
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 org.springframework.jdbc.datasource.DataSourceTransactionManager;
 
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
 

@Configuration
@MapperScan(basePackages = "com.yzy.*.mapper")//掃描dao層mapper接口
public class MyBatisConfig {
 
    /**
     * @return
     * @throws Exception
     * @Primary 必需指定一個且只能有一個主數據源,否則報錯
     */
    @Primary
    @Bean("masterDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.userauth")//根據數據源前綴到application.yml讀取數據源信息//此處改變前綴可以改變默認數據源//
    public DataSource masterDataSource() throws Exception {
        return DataSourceBuilder.create().build();
    }
 
    @Bean("slaverDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.personnel")//根據數據源前綴到application.yml讀取數據源信息//可以配置更多數據源,到前提是application.yml中存在,而且也需要在枚舉類中添加枚舉類型
    public DataSource slaverDataSource() throws Exception {
        return DataSourceBuilder.create().build();
    }
 
    /**
     * @Qualifier 根據名稱進行注入,通常是在具有相同的多個類型的實例的一個注入(例如有多個DataSource類型的實例)
     * @DataSourceTypeAnno(DataSourceEnum.master)事務方法需要指定數據源
     */
    @Bean("dynamicDataSource")
    public DynamicDataSource dynamicDataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
                                               @Qualifier("slaverDataSource") DataSource slaverDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
        targetDataSources.put(DataSourceEnum.master, masterDataSource);
        targetDataSources.put(DataSourceEnum.slaver, slaverDataSource);
 
        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSources);// 該方法是AbstractRoutingDataSource的方法
        dataSource.setDefaultTargetDataSource(masterDataSource);// 默認的datasource設置為myTestDbDataSource
 
        return dataSource;
    }
 
    /**
     * 根據數據源創建SqlSessionFactory
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DynamicDataSource dynamicDataSource,
                                               @Value("mybatis.type-aliases-package") String typeAliasesPackage) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dynamicDataSource);// 指定數據源(這個必須有,否則報錯)
        // 下邊兩句僅僅用於*.xml文件,如果整個持久層操作不需要使用到xml文件的話(只用注解就可以搞定),則不加
        factoryBean.setTypeAliasesPackage(typeAliasesPackage);// 指定實體類所在的包        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapping/**/*Mapper.xml"));//掃描mapper.xml文件包
        return factoryBean.getObject();
    }
 
    /**
     * 配置事務管理器
     */
    @Bean
    public DataSourceTransactionManager transactionManager(DynamicDataSource dataSource) throws Exception {
        return new DataSourceTransactionManager(dataSource);
    }
}

 

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM