日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

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

發布時間:2025/3/19 数据库 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据库读写分离(aop方式完整实现) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近項目要支持讀寫分離, 網上找了很多,但都是不太完整,我自己整理了下供大家參考。
我的項目使用的框架: springMvc+spring+hibernate+springJPA+maven, 數據庫連接池用阿里的druid。


1.?新建一個DynamicDataSource類,?繼承springAbstractRoutingDataSource?類,

并重寫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方式完整实现)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。