最近项目要支持读写分离, 网上找了很多,但都是不太完整,我自己整理了下供大家参考。
我的项目使用的框架: springMvc+spring+hibernate+springJPA+maven, 数据库连接池用阿里的druid。

1. 新建一个DynamicDataSource类, 继承spring的AbstractRoutingDataSource 类,

并重写determineCurrentLookupKey()方法,如下:

package com.dataSource;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/*** 数据源动态切换类* <p>* Copyright: Copyright (c) 2015-3-9 下午3:15:19* <p>* Company: * <p>* * @author macl@c-platform.com* @version 1.0.0*/
public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DataSourceSwitcher.getDataSource();}}

2. 新建DataSourceSwitcher类, 实现数据源选择:

package com.dataSource;import org.springframework.util.Assert;/*** 数据源选择类* <p>* Copyright: Copyright (c) 2015-3-9 下午3:14:55* <p>* Company:  * <p>* * @author macl@c-platform.com* @version 1.0.0*/
public class DataSourceSwitcher {private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();/** 主库(写库) **/public static final String MASTER_DATA_SOURCE = "master";/** 从库(读库) **/public static final String SLAVE_DATA_SOURCE = "slave";public static void setDataSource(String dataSource) {Assert.notNull(dataSource, "dataSource cannot be null");contextHolder.set(dataSource);}public static void setMaster() {clearDataSource();}public static void setSlave() {setDataSource(SLAVE_DATA_SOURCE);}public static String getDataSource() {return (String) contextHolder.get();}public static void clearDataSource() {contextHolder.remove();}
}

3. 新建切面类, 判断如果调用方法以query,list,get方法开头的, 切换为查询库:

package com.dataSource;import java.lang.reflect.Method;
import java.util.List;import org.apache.log4j.Logger;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;/*** 配置AOP切面类,动态切换读/写数据库。* <p>* Copyright: Copyright (c) 2015-3-9 下午3:16:51* <p>* Company:  * <p>* * @author macl@c-platform.com* @version 1.0.0*/
public class DataSourceAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {private static final Logger log = Logger.getLogger(DataSourceAdvice.class);private String logInfo;// 需要切换到从库(读库)的方法名前缀private List<String> slaveMethods;/*** service方法执行之前被调用.*/@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {logInfo = String.format("before切入点:%s-->%s(),切换到:", target.getClass().getName(), method.getName());String methodName = method.getName();boolean hasSwitchedSlave = false;for (String slaveMethod : slaveMethods) {if (methodName.startsWith(slaveMethod)) {if (log.isDebugEnabled()) {log.debug(logInfo + DataSourceSwitcher.SLAVE_DATA_SOURCE);}hasSwitchedSlave = true;DataSourceSwitcher.setSlave();break;}}if (!hasSwitchedSlave) {if (log.isDebugEnabled()) {log.debug(logInfo + "切换到:" + DataSourceSwitcher.MASTER_DATA_SOURCE);}DataSourceSwitcher.setMaster();}}/*** service方法执行完之后被调用.*/@Overridepublic void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {}/*** 抛出Exception之后被调用。* * @param method* @param args* @param target* @param ex* @throws Throwable*/public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {logInfo = String.format("after throwing:%s类中%s方法,", target.getClass().getName(), method.getName());log.error(logInfo + "发生异常:" + ex.getMessage() + ",切换到:" + DataSourceSwitcher.SLAVE_DATA_SOURCE);DataSourceSwitcher.setSlave();}public List<String> getSlaveMethods() {return slaveMethods;}public void setSlaveMethods(List<String> slaveMethods) {this.slaveMethods = slaveMethods;}
}

4.  spring配置文件中, 配置数据源:

5. AOP配置(注意, 可以在service层切换(推荐), 也可以在控制器层切换):

截图为在控制层切换配置, 附件中的context.xml中给的是在service/dao层切换的配置方式。

6.  mvc层支持aop(如果aop切换配置在控制层, 则需要配置这步):

7. 特殊类可以硬编码:

切换到主库 : DataSourceSwitcher.setMaster();

比如 , 登录拦截器RoleGenInterceptor.java --> genLocalSession()

附件下载地址

数据库读写分离(aop方式完整实现)相关推荐

  1. springboot 多数据源 读写分离 AOP方式

    大家好,我是烤鸭: 今天分享springboot读写分离配置.    环境:  springboot  2.1.0.RELEASE          场景说明,目前的需求是 读数据源 * 2 + 写数 ...

  2. 简单好用!利用Spring AOP技术10分钟实现一个数据库读写分离方案

    前言 最近我们的APP在线用户越来越多,接口的响应速度也是越来越慢,经过运维排查发现是由于并发查询太多导致的数据库压力比较大,架构师经过调研给出了数据库读写分离的解决方案,为了快速解决问题,我们最终采 ...

  3. 018:Django商城部署和数据库读写分离

    本章知识点 1.Centos下python3环境的部署 2.Python uwsgi 3.Python uwsgi+nginx部署 4.mysql主从备份介绍 5.Linux下的mysql安装 6.基 ...

  4. Spring 实现数据库读写分离

    Spring 实现数据库读写分离 现在大型的电子商务系统,在数据库层面大都采用读写分离技术,就是一个Master数据库,多个Slave数据库.Master库负责数据更新和实时数据查询,Slave库当然 ...

  5. springboott整合mybatis-plus和sharding-jdbc实现分库分表和读写分离(含完整项目代码)

    springboott整合mybatis-plus和sharding-jdbc实现分库分表和读写分离(含完整项目代码) 一.整合sharding-jdbc 关于springboot整合sharding ...

  6. 一文详解高性能数据库:读写分离

    虽然近十年来各种存储技术飞速发展,但关系数据库由于其 ACID 的特性和功能强大的 SQL 查询,目前还是各种业务系统中关键和核心的存储系统,很多场景下高性能的设计最核心的部分就是关系数据库的设计. ...

  7. mybatis实现数据库读写分离

    ps:本文解决mybatis实现数据库读写分离,项目基础是ruoyi-vue 方案一: 自定义一个注解@DataSource, 利用aop切该注解,切了后设置注解@DataSource的值到Threa ...

  8. Spring - 数据库读写分离

    文章目录 Spring - 数据库读写分离 1.读写分离解决方案 1.1 应用层解决 1.2 中间件解决 2.Mysql主从配置 2.1 Mysql主从复制原理 2.2 Master主库配置 2.3 ...

  9. jedis 读写分离_Redis实现数据库读写分离

    Redis是一种NoSQL的文档数据库,通过key-value的结构存储在内存中,Redis读的速度是110000次/s,写的速度是81000次/s,性能很高,使用范围也很广. 下面用一个实例实现re ...

  10. 解决数据库读写分离(转)

    如何配置mysql数据库的主从? 单机配置mysql主从:http://my.oschina.net/god/blog/496 常见的解决数据库读写分离有两种方案 1.应用层 http://neore ...

最新文章

  1. 做接口测试最重要的知识点
  2. gerrit的Change-Id机制和hook机制
  3. c++如何防止一个类被其他类继承?
  4. linux centos7上安装sql developer
  5. weblogic部署linux静默安装,Linux环境下Weblogic11g中间件-静默安装详解
  6. matlab2014启动很慢,matlab启动慢的解决方法
  7. 116 Python GIL全局解释器锁
  8. hdoj 1054 Strategic Game 最小点覆盖模版题dfs方式(Java版)
  9. 游戏产业链:游戏引擎
  10. 2022程序员都推荐的算法编程课程终于来了!新手从入门到面试考点全覆盖,学到就是赚到!...
  11. MySQL与CVM自建数据库优势_UCloud云数据库MySQL产品优势及与自建数据库对比
  12. 【硬核】肝了一个月,Cisco网络工程师知识点总结
  13. 医院信息科结构化面试
  14. WRKY转录因子通过促进GhMKK2介导的类黄酮生物合成调节棉花对尖孢镰刀菌的抗性
  15. selenium 页面加载超时处理
  16. 怎样提高解决问题的能力
  17. echarts实现某个市3D地图展示
  18. 【Xasset谷歌分包】打包AAB并上传谷歌商店操作流程分享
  19. freeRTOS移植——ZYNQ7000简介
  20. python中quote函数是什么意思

热门文章

  1. abap 选择屏幕事件AT SELECTION-SCREEN
  2. 从《我要投资》,看麓谷基金广场的“孤峰优势”
  3. matlab 度分秒转换成度_如何利用matlab统一处理照片亮度对比度
  4. java gridbag_java – 调整Gridbag布局
  5. java 泛型集合应用_Java泛型集合的应用和方法
  6. Javaweb-----HTTP协议
  7. php 多维素组添加下级,php中如何将元素添加到多维数组
  8. python中%r和%s的区别
  9. Python字典的排序方法,你用对了吗
  10. python中的及||