前言相信有经验的同学都知道,当db的读写量过高时,我们会备份一个或多个从库进行数据备份然后主库主要负责写功能(也有阅读的需求,但压力不大)。当db分主从库时,我们还需要在项目中自动连接主从库,实现读写。分离效果。实现读写分离并不难,只要在数据库连接池中手动控制对应的db服务地址即可,但那样会侵入业务代码,而且一个项目操作数据库的地方可能很多。如果全部由人工控制,无疑是一项很大的工作量,为此,我们有必要改造一套方便的工具。就Java语言而言,如今的大部分项目都是基于SpringBoot框架来搭建项目结构的。结合Spring本身自带的AOP工具,我们可以很方便的构建出可以达到读写分离效果的注解类。可以达到不侵入业务代码的效果,使用起来更方便。下面就简单带大家写个demo。环境部署数据库:MySql库数量:2个,一主一从。关于mysql的主从环境部署网上有很多文章可以参考,这里就不介绍了。启动项目首先,毫无疑问,开始搭建一个SpringBoot项目,然后在pom文件中引入如下依赖:com.alibabadruid-spring-boot-starter1.1.10org.mybatis.spring.bootmybatis-spring-boot-starter1.3.2tk.mybatismapper-spring-boot-starter2.1.5mysqlmysql-connector-java8.0.16org.springframework.bootspring-boot-starter-jdbc提供org.springframework.bootspring-boot-starter-aop提供org.springframework.bootspring-boot-starter-weborg.projectlomboklomboktruecom.alibabafastjson1.2.4org.springframework.bootspring-boot-starter-test测试org.springframework.bootspring-boot-starter-data-jpa目录结构引入基本依赖后,梳理目录结构,完成的项目骨架为大致如下:建表创建表user,在主库执行sql语句在从库生成对应的表数据DROPTABLEIFEXISTS`user`;CREATETABLE`user`(`user_id`bigint(20)NOTNULLCOMMENT'用户id',`user_name`varchar(255)DEFAULT''COMMENT'用户名',`user_phone`varchar(50)DEFAULT''COMMENT'用户电话',`address`varchar(255)DEFAULT''COMMENT'地址',`weight`int(3)NOTNULLDEFAULT'1'COMMENT'权重大者优先',`created_at`datetimeNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',`updated_at`datetimeDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT'更新时间',PRIMARYKEY(`user_id`CH))ENGINE=InnoDBDEFAVALUES('1196978513958141952','测试1','18826334748','广州市海珠区','1','2019-0:11-228:51','2019-11-2214:28:26');INSERTINTO`user`VALUES('1196978513958141953','测试2','18826274230','广州市天河区','2','2019-11-2010:29:37','2019-11-2214:28:14');插入`user`VALUES('1196978513958141954','test3','18826273900','广州市天河区','1','2019-11-2010:30:19','2019-11-2214:28:30');主从数据源配置应用.yml,主要信息为主从数据库服务器的数据源配置:port:8001spring:jackson:date-format:yyyy-MM-ddHH:mm:sstime-zone:GMT+8datasource:type:com.alibaba.druid.pool.DruidDataSourcedriver-class-name:com.mysql.cj.jdbc.Drivermaster:url:jdbc:mysql://127.0.0.1:3307/user?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&useSSL=false&zeroDateTimeBehavi=convertToNull&allowMultiQueries=trueusername:rootpassword:slave:url:jdbc:mysql://127.0.0.1:3308/user?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8OverRead&autofalse&useSSL=false&zeroDateTimeBehavior=convertToNull&allowMultiQueries=trueusername:rootpassword:因为有两个数据源,一主一从,我们用枚举类代替,这样就可以对应@GetterpublicenumDynamicDataSourceEnum{MASTER("master"),SLAVE("slave");优先vateStringdataSourceName;DynamicDataSourceEnum(StringdataSourceName){this.dataSourceName=dataSourceName;}}数据源配置信息类DataSourceConfig,这里配置了两个数据源,masterDb和slaveDb@Configuration@MapperScan(basePackages="com.xjt.proxy.mapper",sqlSessionTemplateRef="sqlTemplate")publicclassDataSourceConfig{//主库@Bean@ConfigurationProperties(prefix="spring.datasource.master")publicDataSourcemasterDb(){returnDruidDataSourceBuilder.create().build();}/***来自库*/@Bean@ConditionalOnProperty(prefix="spring.datasource",name="slave",matchIfMissing=true)@ConfigurationProperties(prefix="spring.datasource.slave")publicDataSourceslaveDb(){returnDruidDataSourceBuilder.create().build();}/***主从动态配置*/@BeanpublicDynamicDataSourcedynamicDb(@Qualifier("masterDb")DataSourcemasterDataSource,@Autowired(required=false)@Qualifier("slaveDb")DataSourceslaveDataSource){DynamicDataSourcedynamicDataSource=newDynamicDataSourcece();Map