springboot读写分离

前言:本文采用springboot集成AOP的方式实现读写分离

1.准备工作,mybaties主从数据库的搭建,不会的同学可以浏览这篇博客https://blog.csdn.net/qq_30374237/article/details/106624263

2.引入依赖

 <!--导入AOP依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- 数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.31</version>
        </dependency>

3.添加主从库的配置

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.master.url=jdbc:mysql://192.168.1.156:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&useSSL=false&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
spring.datasource.master.username=root
spring.datasource.master.password=****
spring.datasource.slave.url=jdbc:mysql://192.168.1.154:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&useSSL=false&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
spring.datasource.slave.username=root
spring.datasource.slave.password=****

4.定义线程类,用于从库的设置,清空和获取

public class DataSourceThread {
    private static final ThreadLocal<String> DATASOURCE_THREAD = new ThreadLocal<>();

    public static void set() {
        DATASOURCE_THREAD.set("slave");
    }

    public static String get() {
        return DATASOURCE_THREAD.get();
    }

    public static void clear() {
        DATASOURCE_THREAD.remove();
    }

5.由于多个数据源,数据库配置需要手动配置

@Configuration
@MapperScan("com.bjiang.datasource.read.write.dao")
public class ReadOrWriteDaraSource {
    /**
     * 主库配置注入
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource master() {
        //new DruidDataSource();
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * 从库配置注入
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slave() {
        //new DruidDataSource();
        return DruidDataSourceBuilder.create().build();
    }
    /**
     * 主从动态配置
     */
    @Bean
    public SlaveDataSource dynamic(@Qualifier("master") DataSource masterDataSource,
                                       @Autowired(required = false) @Qualifier("slave") DataSource slaveDataSource) {
        SlaveDataSource dynamicDataSource = new SlaveDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("master", masterDataSource);
        if (slaveDataSource != null) {
            targetDataSources.put("slave", slaveDataSource);
        }
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(masterDataSource);
        return dynamicDataSource;
    }
/*
* 多个数据源需要配置SqlSessionFactory
* */
    @Bean
    public SqlSessionFactory sessionFactory(@Qualifier("dynamic") DataSource dynamicDataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setTypeAliasesPackage("com.bjiang.datasource.read.write.dao");
        bean.setDataSource(dynamicDataSource);
        return bean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlTemplate(@Qualifier("sessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = "dataSource")
    public DataSourceTransactionManager dataSource(@Qualifier("dynamic") DataSource dynamicDataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dynamicDataSource);
        return dataSourceTransactionManager;
    }

6.重写方法,设置以及获取DataSource

public class SlaveDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceThread.get();
    }
}

7.自定义注解实现AOP,用于注解需要使用从库的方法

/**
 * 自定义注解实现AOP,用于注解需要使用从库的方法
 * */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Slave {
}

8.编写AOP类进行拦截,实现切换数据源

@Aspect
@Order(value = 1)
@Component
public class DataSourceAop {
    @Around("@annotation(com.bjiang.datasource.read.write.aop.Slave)")
    public Object setDynamicDataSource(ProceedingJoinPoint pjp) throws Throwable {
        boolean clear = true;
        try {
            DataSourceThread.set();
            log.info("切换数据源");
            return pjp.proceed();
        } finally {
            if (clear) {
                DataSourceThread.clear();
            }
        }
    }
}

9.编写测试方法,需要使用从库时加上注解@Slave

10.测试

显示主库数据已插入

显示查看数据时已切换数据源

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值