背景

数据库配置主从之后,如何在代码层面实现读写分离?
用户自定义设置数据库路由
Spring boot提供了AbstractRoutingDataSource根据用户定义的规则选择当前的数据库,这样我们可以在执行查询之前,设置读取从库,在执行完成后,恢复到主库。
实现可动态路由的数据源,在每次数据库查询操作前执行
ReadWriteSplitRoutingDataSource.java
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* @author songrgg
* @since 1.0
*/
public class ReadWriteSplitRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DbContextHolder.getDbType();
}
}
线程私有路由配置,用于ReadWriteSplitRoutingDataSource动态读取配置
DbContextHolder.java
/**
* @author songrgg
* @since 1.0
*/
public class DbContextHolder {
public enum DbType {
MASTER,
SLAVE
}
private static final ThreadLocal<DbType> contextHolder = new ThreadLocal<>();
public static void setDbType(DbType dbType) {
if(dbType == null){
throw new NullPointerException();
}
contextHolder.set(dbType);
}
public static DbType getDbType() {
return contextHolder.get() == null ? DbType.MASTER : contextHolder.get();
}
public static void clearDbType() {
contextHolder.remove();
}
}
AOP优化代码
利用AOP将设置数据库的操作从代码中抽离,这里的粒度控制在方法级别,所以利用注解的形式标注这个方法涉及的数据库事务只读,走从库。
只读注解,用于标注方法的数据库操作只走从库。
ReadOnlyConnection.java
package com.wallstreetcn.hatano.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates the database operations is bound to the slave database.
* AOP interceptor will set the database to the slave with this interface.
* @author songrgg
* @since 1.0
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ReadOnlyConnection {
}
ReadOnlyConnectionInterceptor.java
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
/**
* Intercept the database operations, bind database to read-only database as this annotation
* is applied.
* @author songrgg
* @since 1.0
*/
@Aspect
@Component
public class ReadOnlyConnectionInterceptor implements Ordered {
private static final Logger logger = LoggerFactory.getLogger(ReadOnlyConnectionInterceptor.class);
@Around("@annotation(readOnlyConnection)")
public Object proceed(ProceedingJoinPoint proceedingJoinPoint, ReadOnlyConnection readOnlyConnection) throws Throwable {
try {
logger.info("set database connection to read only");
DbContextHolder.setDbType(DbContextHolder.DbType.SLAVE);
Object result = proceedingJoinPoint.proceed();
return result;
} finally {
DbContextHolder.clearDbType();
logger.info("restore database connection");
}
}
@Override
public int getOrder() {
return 0;
}
}
UserService.java
@ReadOnlyConnection
public List<User> getUsers(Integer page, Integer limit) {
return repository.findAll(new PageRequest(page, limit));
}
配置Druid数据库连接池
build.gradle
compile("com.alibaba:druid:1.0.18")
groovy依赖注入
配置dataSource为可路由数据源
context.groovy
import com.alibaba.druid.pool.DruidDataSource
import DbContextHolder
import ReadWriteSplitRoutingDataSource
** SOME INITIALIZED CODE LOAD PROPERTIES **
def dataSourceMaster = new DruidDataSource()
dataSourceMaster.url = properties.get('datasource.master.url')
println("master set to " + dataSourceMaster.url)
dataSourceMaster.username = properties.get('datasource.master.username')
dataSourceMaster.password = properties.get('datasource.master.password')
def dataSourceSlave = new DruidDataSource()
dataSourceSlave.url = properties.get('datasource.slave.url')
println("slave set to " + dataSourceSlave.url)
dataSourceSlave.username = properties.get('datasource.slave.username')
dataSourceSlave.password = properties.get('datasource.slave.password')
beans {
dataSource(ReadWriteSplitRoutingDataSource) { bean ->
targetDataSources = [
(DbContextHolder.DbType.MASTER): dataSourceMaster,
(DbContextHolder.DbType.SLAVE): dataSourceSlave
]
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Spring
# boot读写分离
# spring数据库读写分离
# 使用springboot aop来实现读写分离和事物配置
# SpringBoot自定义注解使用读写分离Mysql数据库的实例教程
# SpringBoot整合MyCat实现读写分离的方法
# Springboot + Mysql8实现读写分离功能
# spring boot + mybatis如何实现数据库的读写分离
# springboot基于Mybatis mysql实现读写分离
# 详解Spring Boot中整合Sharding-JDBC读写分离示例
# spring boot配置读写分离的完整实现步骤
# SpringBoot集成Spring Data JPA及读写分离
# Spring Boot 结合 aop 实现读写分离
# 我们可以
# 自定义
# 大家多多
# 数据库查询
# 连接池
# 完成后
# 如何在
# clearDbType
# throw
# null
# remove
# set
# NullPointerException
# dbType
# ThreadLocal
# lt
# static
# final
# void
# setDbType
相关文章:
股票网站制作软件,网上股票怎么开户?
如何在云主机快速搭建网站站点?
家庭服务器如何搭建个人网站?
如何在Windows服务器上快速搭建网站?
免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?
制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?
如何在IIS7上新建站点并设置安全权限?
建站之星后台密码遗忘如何找回?
唐山网站制作公司有哪些,唐山找工作哪个网站最靠谱?
如何用低价快速搭建高质量网站?
linux top下的 minerd 木马清除方法
小建面朝正北,A点实际方位是否存在偏差?
如何在建站主机中优化服务器配置?
建站之星如何取消后台验证码生成?
seo网站制作优化,网站SEO优化步骤有哪些?
建站主机是否等同于虚拟主机?
音响网站制作视频教程,隆霸音响官方网站?
公司网站制作费用多少,为公司建立一个网站需要哪些费用?
企业宣传片制作网站有哪些,传媒公司怎么找企业宣传片项目?
网站制作培训多少钱一个月,网站优化seo培训课程有哪些?
如何在新浪SAE免费搭建个人博客?
微信推文制作网站有哪些,怎么做微信推文,急?
如何通过宝塔面板实现本地网站访问?
如何快速生成ASP一键建站模板并优化安全性?
Dapper的Execute方法的返回值是什么意思 Dapper Execute返回值详解
黑客如何通过漏洞一步步攻陷网站服务器?
制作网站的过程怎么写,用凡科建站如何制作自己的网站?
高防服务器租用指南:配置选择与快速部署攻略
官网建站费用明细查询_企业建站套餐价格及收费标准指南
已有域名建站全流程解析:网站搭建步骤与建站工具选择
头像制作网站在线制作软件,dw网页背景图像怎么设置?
巅云智能建站系统:可视化拖拽+多端适配+免费模板一键生成
建站主机类型有哪些?如何正确选型
,怎么在广州志愿者网站注册?
教学网站制作软件,学习*后期制作的网站有哪些?
SAX解析器是什么,它与DOM在处理大型XML文件时有何不同?
无锡营销型网站制作公司,无锡网选车牌流程?
Python路径拼接规范_跨平台处理说明【指导】
建站主机功能解析:服务器选择与快速搭建指南
如何在阿里云高效完成企业建站全流程?
车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?
建站主机如何选?高性价比方案全解析
香港服务器选型指南:免备案配置与高效建站方案解析
正规网站制作公司有哪些,目前国内哪家网页网站制作设计公司比较专业靠谱?口碑好?
网站制作软件免费下载安装,有哪些免费下载的软件网站?
网站制作的方法有哪些,如何将自己制作的网站发布到网上?
移民网站制作流程,怎么看加拿大移民官网?
攀枝花网站建设,攀枝花营业执照网上怎么年审?
,网页ppt怎么弄成自己的ppt?
如何优化Golang Web性能_Golang HTTP服务器性能提升方法
*请认真填写需求信息,我们会在24小时内与您取得联系。