springboot+mybatis配置多数据源+aop动态数据源切换

最近告诉项目需要做多数据源得配置,鼓捣了很久,一直没有做aop得数据源切换,一直只能调用默认得是具有,在网上找了一些资料进行了配置,项目能够成功得进行数据源得切换,把心得保存下来和大家分享一下。

1.数据库多数据源配置

springboot+mybatis配置多数据源+aop动态数据源切换springboot+mybatis配置多数据源+aop动态数据源切换

2.自定义一个数据源配置类DataSourceConfigurer

@Configuration
public class DataSourceConfigurer {

    //主数据源
    @Bean(name = "writingDataSource")
   /* @Qualifier("writingDataSource")*/
    @ConfigurationProperties(prefix ="spring.datasource.writing")
    /*@Primary//配置该数据源为主数据源*/
    public DataSource writingDataSource(){return DataSourceBuilder.create().build();}



    //从数据源
    @Bean(name = "userDataSource")//装配该方法返回值为userDataSource管理bean
   /* @Qualifier("userDataSource")*///spring装配bean唯一标识
    @ConfigurationProperties(prefix="spring.datasource.user")//application.yml文件内配置数据源的前缀
    public DataSource userDataSource(){return DataSourceBuilder.create().build();}



    @Primary//设置默认数据源
    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 默认数据源
        dynamicDataSource.setDefaultTargetDataSource(writingDataSource());
        // 配置多数据源
        Map<Object, Object> dsMap = new HashMap();
        dsMap.put("writingDataSource", writingDataSource());
        dsMap.put("userDataSource", userDataSource());

        dynamicDataSource.setTargetDataSources(dsMap);
        return dynamicDataSource;
    }

    /**
     * 配置@Transactional注解事物
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }

3.创建一个类DynamicDataSource获取数据源名

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        System.out.println("数据源为"+DataSourceContextHolder.getDB());
        return DataSourceContextHolder.getDB();
    }
}


4.创建DataSourceContextHolder类,对数据源进行操作。

public class DataSourceContextHolder {

    /**
     * 默认数据源
     */
    public static final String DEFAULT_DS = "writingDataSource";

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

    // 设置数据源名
    public static void setDB(String dbType) {
        System.out.println("切换到{"+dbType+"}数据源");
        contextHolder.set(dbType);
    }

    // 获取数据源名
    public static String getDB() {
        return (contextHolder.get());
    }

    // 清除数据源名
    public static void clearDB() {
        contextHolder.remove();
    }
}

5.自定义一个注解(@DC)

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DS {
    String value() default "writingDataSource";
}

6.动态切换数据源DynamicDataSourceAspect类

@Aspect
@Component
public class DynamicDataSourceAspect {
    @Before("@annotation(DS)")
    public void beforeSwitchDS(JoinPoint point){
        //获得当前访问的class
        Class<?> className = point.getTarget().getClass();
        //获得访问的方法名
        String methodName = point.getSignature().getName();
        //得到方法的参数的类型
        Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
        String dataSource = DataSourceContextHolder.DEFAULT_DS;
        try {
            // 得到访问的方法对象
            Method method = className.getMethod(methodName, argClass);
            // 判断是否存在@DS注解
            if (method.isAnnotationPresent(DS.class)) {
                DS annotation = method.getAnnotation(DS.class);
                // 取出注解中的数据源名
                dataSource = annotation.value();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 切换数据源
        DataSourceContextHolder.setDB(dataSource);
    }

    @After("@annotation(DS)")
    public void afterSwitchDS(JoinPoint point){
        DataSourceContextHolder.clearDB();
    }
}

7配置完成之后调用controller层里面得方法,在serviceImpl得方法中加上注解,确定调用得是哪个数据库,

@DS("writingDataSource")租借表示调用得是writingDataSource数据源

@Override
@DS("writingDataSource")
public Message excellentList(Message message) {
    List<TbWorks> list=tbWorksMapper.excellentList();
    PageInfo pageInfo = new PageInfo(list);
    message.setData(pageInfo);
    message.setCode("200");
    message.setMsg("查询成功");
    return message;
}