Springboot系列--简单的配置实现数据库读写分离
2019-09-17 23:48
441 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Fzicoo/article/details/100944358
1 配置文件
#多数据源 datasource: #从库数量 readSize: 2 # 使用druid数据源 type: com.alibaba.druid.pool.DruidDataSource #主库 master: url: jdbc:mysql://127.0.0.1:3306/master?useUnicode=true&characterEncoding=utf8 username: root password: xxx driver-class-name: com.mysql.jdbc.Driver filters: stat maxActive: 20 initialSize: 1 maxWait: 60000 minIdle: 1 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQueryTimeout: 900000 validationQuery: SELECT 1 testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxOpenPreparedStatements: 20 slave: url: jdbc:mysql://127.0.0.1:3306/slave?useUnicode=true&characterEncoding=utf8 username: root password: xxx driver-class-name: com.mysql.jdbc.Driver filters: stat maxActive: 20 initialSize: 1 maxWait: 60000 minIdle: 1 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQueryTimeout: 900000 validationQuery: SELECT 1 testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxOpenPreparedStatements: 20
这里我只配置了一个主库和一个从库,你也可以配置多个从库,根据你自己项目需求来。
2 DataSourceConfig
@Configuration public class DataSourceConfig { @Value("${datasource.type}") private Class<? extends DataSource> dataSourceType; @Bean(name = "masterDataSource") @ConfigurationProperties(prefix = "datasource.master") public DataSource masterDataSource() { return DataSourceBuilder.create().type(dataSourceType).build(); } @Bean(name = "slaveDataSource") @ConfigurationProperties(prefix = "datasource.slave") public DataSource slaveDataSource() { return DataSourceBuilder.create().type(dataSourceType).build(); } //动态数据源 @Bean(name = "dynamicDataSource") //解决互相依赖关系 @DependsOn({ "masterDataSource", "slaveDataSource"}) @Primary public DataSource getDataSource() { DynamicDataSource dataSource = new DynamicDataSource(); dataSource.setTargetDataSources(targetDataSources()); return dataSource; } private Map<Object, Object> targetDataSources() { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put(DataSourceType.MASTER.getType(), masterDataSource()); targetDataSources.put(DataSourceType.SLAVE.getType(), slaveDataSource()); return targetDataSources; } }
3 主从库枚举
public enum DataSourceType { SLAVE("slave", "从库"), MASTER("master", "主库"); private String type; private String name; DataSourceType(String type, String name) { this.type = type; this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
4 通过继承AbstractRoutingDataSource实现其动态选择数据源
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { if (DynamicDataSourceHolder.getDataSouce() != null) { return DynamicDataSourceHolder.getDataSouce(); } return DataSourceType.MASTER.getType(); } }
5 设置本地线程全局变量,保证线程安全
public class DynamicDataSourceHolder { private static final ThreadLocal<String> holder = new ThreadLocal<>(); public static void putDataSource(DataSourceType dataSourceType) { holder.set(dataSourceType.getType()); } public static String getDataSouce() { return holder.get(); } }
6 自定义注解
import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented @Inherited public @interface DataSource { /** * 数据库路由 */ DataSourceType value() default DataSourceType.MASTER; }
7 AOP进行动态数据源操作
这个是核心,处理读写分离和自定义注解
ps:我写了两个类切面,DataSourcePartAspect 这个先执行,默认mapper有select,query的走从库 ;delete,update,insert走主库
DataSourceAspect后执行,也就是注解的优先级高于前面的默认的,保证注解优先。
@Aspect @Component @Order(-1) @Slf4j public class DataSourcePartAspect { /** * mapper 查询操作默认使用从库 */ @Before("execution(* com..service..*.select*(..)) || execution(* com..service..*.get*(..))|| execution(* com..service..*.query*(..))") public void setReadDataSourceType() { DynamicDataSourceHolder.putDataSource(DataSourceType.SLAVE); log.info("dataSource 切换到:{}",DataSourceType.SLAVE.getName()); } /** * mapper 修改删除操作默认使用主库库 */ @Before("execution(* com..service..*.insert*(..)) || execution(* com..service..*.update*(..)) || execution(* com..service..*.delete*(..))") public void setWriteDataSourceType() { DynamicDataSourceHolder.putDataSource(DataSourceType.MASTER); log.info("dataSource 切换到:{}",DataSourceType.MASTER.getName()); } }
import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Aspect @Component @Order(0) @Slf4j public class DataSourceAspect{ /** * 注解方式 * @param joinPoint * @param dataSource */ @Before(value = "@annotation(dataSource)") public void dataSourcePoint(JoinPoint joinPoint, DataSource dataSource) { DynamicDataSourceHolder.putDataSource(dataSource.value()); } }
@Component public class TestService{ @Autowired private SourceMapper sourceMapper; @DataSource(DataSourceType.MASTER) public String save() { System.out.println(this.sourceMapper.deleteByPrimaryKey("1")); return null; } //没有注解默认走主库 //@DataSource(DataSourceType.SLAVE) public String query() { System.out.println("查询结果:" + JSONObject.toJSONString(this.sourceMapper.selectByPrimaryKey("1"))); return null; } }
相关文章推荐
- Spring Boot2.0.3 Mybatis Sharding-jdbc3.X集成实现数据库的读写分离(一)MySql的主从配置
- SpringMVC+ Mybatis 配置多数据源 + 自动数据源切换 + 实现数据库读写分离
- Spring+Mybatis 实现aop数据库读写分离与多数据库源配置操作
- 通过Spring Boot配置动态数据源访问多个数据库的实现代码
- Spring-Boot 多数据源配置+动态数据源切换+多数据源事物配置实现主从数据库存储分离
- mysql+spring+mybatis实现数据库读写分离[代码配置]
- Spring 配置多数据源实现数据库读写分离
- 实现一个无需配置的SpringBoot的简单Demo
- Spring Boot 揭秘与实战 自己实现一个简单的自动配置模块
- mysql+spring+mybatis实现数据库读写分离[代码配置]
- Spring 配置多数据源实现数据库读写分离
- Spring 配置多数据源实现数据库读写分离
- mysql+spring+mybatis实现数据库读写分离[代码配置] .
- Spring Boot 揭秘与实战 自己实现一个简单的自动配置模块
- Spring Boot2.0.3 Mybatis Sharding-jdbc3.X集成实现数据库的读写分离(二)-项目实现
- springboot中使用@EnableScheuling注解来实现数据库配置定时任务
- mysql+spring+mybatis实现数据库读写分离的代码配置
- SpringBoot系列——利用系统环境变量与配置文件的分支选择实现“智能部署”
- mysql+spring+mybatis实现数据库读写分离[代码配置]
- Spring Boot系列教程五:使用properties配置文件实现多环境配置