• 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);
        }
    }


  • 相关阅读:
    微信小程序,答题问卷,单选,多选混合在一个借口,前端怎么循环
    react 从0到1
    react从0到0
    es6 系统总结
    点击页面的某个元素,弹出这个元素的索引(是第几个)
    js return的用法
    安装golang.org/x/*
    完美解决从github上下载东西慢的方法
    初探golang和应用其框架 gin 的 使用教程(一)安装篇
    CentOS7安装go开发环境
  • 原文地址:https://www.cnblogs.com/yzyBalance/p/11423436.html
Copyright © 2020-2023  润新知