jeecg主从数据库读写分离配置「建议收藏」

1、修改Dbconfig.properties数据库配置文件:注意:从库属性的名字要与主库的属性名字区分开,属性名将会在后面的配置文件中用到。#数据库配置主库-写入库#MySQLhibernate.dialect=org.hibernate.dialect.MySQLDialectvalidationQuery.sqlserver=SELECT1jdbc.url=jdbc\:mys…

大家好,又见面了,我是你们的朋友全栈君。

1、修改Dbconfig.properties数据库配置文件:
注意:从库属性的名字要与主库的属性名字区分开,属性名将会在后面的配置文件中用到。

#数据库配置 主库-写入库
#MySQL
hibernate.dialect=org.hibernate.dialect.MySQLDialect
validationQuery.sqlserver=SELECT 1
jdbc.url=jdbc\:mysql\://127.0.0.1\:3306/database001?useUnicode\=true&characterEncoding\=UTF-8
jdbc.username=root
jdbc.password=root
jdbc.dbType=mysql
#数据库配置 从库-读库
#MySQL
jdbc.url.slave=jdbc\:mysql\://127.0.0.1\:3306/database002?useUnicode\=true&characterEncoding\=UTF-8
jdbc.username.slave=root
jdbc.password.slave=root
jdbc.dbType.slave=mysql
#更新|创建|验证数据库表结构|不作改变     默认update(create,validate,none)
hibernate.hbm2ddl.auto=none

2、修改spring-mvc-hibernate.xml配置文件
2.1、配置数据源2:复制原有的数据源配置,做以下修改:
1) 数据源的名称name需要重新命名;
2) 将数据库的链接属性设定为Dbconfig.properties中数据源2的属性值。

	<!-- 配置数据源2 -->
	<bean name="dataSource_slave" class="com.alibaba.druid.pool.DruidDataSource"
		init-method="init" destroy-method="close">
		<property name="url" value="${jdbc.url.jeewx.slave}" />
		<property name="username" value="${jdbc.username.jeewx.slave}" />
		<property name="password" value="${jdbc.password.jeewx.slave}" />
		<!-- 初始化连接大小 -->
		<property name="initialSize" value="0" />
		<!-- 连接池最大使用连接数量 -->
		<property name="maxActive" value="250" />
		<!-- 连接池最大空闲 -->
		<property name="maxIdle" value="20" />
		<!-- 连接池最小空闲 -->
		<property name="minIdle" value="5" />
		<!-- 获取连接最大等待时间 -->
		<property name="maxWait" value="60000" />
		<!-- <property name="poolPreparedStatements" value="true" /> <property 
			name="maxPoolPreparedStatementPerConnectionSize" value="33" /> -->
		<property name="validationQuery" value="${validationQuery.sqlserver}" />
		<property name="testOnBorrow" value="false" />
		<property name="testOnReturn" value="false" />
		<property name="testWhileIdle" value="true" />

		<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
		<property name="timeBetweenEvictionRunsMillis" value="60000" />
		<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
		<property name="minEvictableIdleTimeMillis" value="25200000" />

		<!-- 打开removeAbandoned功能 -->
		<property name="removeAbandoned" value="true" />
		<!-- 1800秒,也就是30分钟 -->
		<property name="removeAbandonedTimeout" value="1800" />
		<!-- 关闭abanded连接时输出错误日志 -->
		<property name="logAbandoned" value="true" />

		<!-- 开启Druid的监控统计功能 -->
		<property name="filters" value="stat" />
		<!--<property name="filters" value="mergeStat" /> -->
		<!-- Oracle连接是获取字段注释 -->
		<property name="connectProperties">
			<props>
				<prop key="remarksReporting">true</prop>
			</props>
		</property>
	</bean>

2.2、配置数据源集:

     <!-- 数据源集合 -->
	<bean id="dataSource"
		class="org.jeecgframework.core.extend.datasource.DynamicDataSource">
		<property name="targetDataSources">
			<map key-type="org.jeecgframework.core.extend.datasource.DataSourceType">
				<entry key="dataSource_jeecg" value-ref="dataSource_jeecg" />
				<entry key="dataSource_slave" value-ref="dataSource_slave" />
				<!-- <entry key="mapdataSource" value-ref="mapdataSource" /> -->
			</map>
		</property>
		<property name="defaultTargetDataSource" ref="dataSource_jeecg" />
	</bean>

2.3、定义AOP的切面处理器,关于AOP的语法自行百度查阅,其中重点对以下做说明:
(1) org.jeecgframework.core.interceptors.DataSourceAspect类需要实现,该类主要用来对数据库进行动态切换;
(2) 此处的表达式设定的主要是是针对该包下的CommonService的所有方法进行切面处理;
(3) DataSourceAspect类中必须实现before方法,具体实现对数据库的动态切换就在此控制。

    <!-- 定义AOP切面处理器 -->
    <bean class="org.jeecgframework.core.interceptors.DataSourceAspect" id="dataSourceAspect" />
    <aop:config>
        <!-- 定义切面,CommonService的所有方法 -->
        <aop:pointcut id="txPointcut" expression="execution(* org.jeecgframework.core.common.service.*.*(..))" />
        <!-- 将切面应用到自定义的切面处理器上,-9999保证该切面优先级最高执行 -->
        <aop:aspect ref="dataSourceAspect" order="-9999">
            <aop:before method="before" pointcut-ref="txPointcut" />
        </aop:aspect>
    </aop:config>

3、实现类org.jeecgframework.core.interceptors.DataSourceAspect:

package org.jeecgframework.core.interceptors;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.jeecgframework.core.extend.datasource.DataSourceContextHolder;

/**
 * 定义数据源的AOP切面,通过该Service的方法名判断是应该走读库还是写库
 * 
 * @author yaoxy
 *
 */
public class DataSourceAspect {
    /**
     * 在进入Service方法之前执行
     * 
     * @param point 切面对象
     */
    public void before(JoinPoint point) {
        // 获取到当前执行的方法名
        String methodName = point.getSignature().getName();
        if (isSlave(methodName)) {
            // 标记为读库
        	DataSourceContextHolder.markSlave();
        } else {
            // 标记为写库
        	DataSourceContextHolder.markMaster();
        }
    }
    /**
     * 判断是否为读库
     * 
     * @param methodName
     * @return
     */
    private Boolean isSlave(String methodName) {
        // 方法名以query、find、get开头的方法名走从库
        return StringUtils.startsWithAny(methodName, "query","find","get");
    }
}

实现原理:
1) 判断AOP切面处理的CommonService类中被调用的方法名开头中是否包含查询的关键字;
2) 如果CommonService被调用的方法中包含查询的关键字,调用DataSourceContextHolder将库切换到从库进行读取操作,否则切换到主库进行写入操作。
4、DataSourceContextHolder中追加主从切换的方法

ackage org.jeecgframework.core.extend.datasource;
/**
 *类名:DataSourceContextHolder.java
 *功能:获得和设置上下文环境的类,主要负责改变上下文数据源的名称
 */
public class DataSourceContextHolder {
    //读库对应的数据源key
	private static final ThreadLocal contextHolder=new ThreadLocal();
	public static void setDataSourceType(DataSourceType dataSourceType){
		contextHolder.set(dataSourceType);
	}
	public static DataSourceType getDataSourceType(){
		return (DataSourceType) contextHolder.get();
	}
	public static void clearDataSourceType(){
		contextHolder.remove();
	}
	/**
     * 标记写库
     */
    public static void markMaster(){
    	setDataSourceType(DataSourceType.dataSource_jeecg);
    }
    /**
     * 标记读库
     */
    public static void markSlave(){
    	setDataSourceType(DataSourceType.dataSource_slave);
    }
	
}

5、数据源的枚举类DataSourcetype中追加新增的从库数据源名称

package org.jeecgframework.core.extend.datasource;

public enum DataSourceType {
	dataSource_jeecg,dataSource_enter,dataSource4,mapdataSource,dataSource_slave
	//dataSource_jeecg:主库名,dataSource_slave:从库名。
}

总结:
应用层的读写分析涉及到以下5个文件,详见文件夹【应用层读写分离设定文件】:
在这里插入图片描述
实现的原理:利用Spring AOP的切面处理原理,在对数据库进行操作的方法被执行之前根据方法的名字判断是读还是写,进行主从/读写数据库的切换。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/127994.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 程序员在外包公司工作怎么样呢_从外包公司出来好找工作吗

    程序员在外包公司工作怎么样呢_从外包公司出来好找工作吗    今天刚刚好是周六,本来是可以好好休息的,计划好要去哪里玩的,但是天有不测风云,突然说银行领导要来检查,今天周末大家必须和平时一样照常上班,天呐!大哭!也无奈,只能照常上班咯,谁让别人是地主呢?我经常看到帖子上说或者论坛上大家在讨论程序员在外包公司工作怎么样?福利待遇好吗?工作累吗?上班时间怎么样?等等总之一堆一堆的,现在下班回家闲来无事,我就来说说在外包公司工作到底怎么样?是一种什么样的感觉?大家想不想听呢?那就让我慢慢道来…  &n

    2022年9月30日
    3
  • 手把手教你搭建基于ngrok私有云存储服务「建议收藏」

    手把手教你搭建基于ngrok私有云存储服务「建议收藏」前段时间,闲置了个1核1G1M的服务器,就搞了个树莓派玩玩,随手搭建了个私有云存储,也看了一些教程,发现坑比较多,自己就重写个准备工作申请域名,如domain.cn可远程访问的服务器一台(linux64),并且备案(未备案域名只能用大陆外服务器)设置域名解析,如ngrok.domain.cn申请域名所需SSL证书(非必须,除非你要开启https访问)服务端安装服务器安装unzip解压命令yuminstall-yunzip下载服务端文件server.zip解压后启动,启动

    2022年6月22日
    23
  • shell高级技巧:提取vcf文件中一个contig

    shell高级技巧:提取vcf文件中一个contig这是一个很小众的需求 大部分变异检测都是基于组装质量比较高的基因组 而不是那种初步拼接的 contig 由于初步拼接的参考序列通常会有成千上万个 contig 序列 也就导致在 VCF 的头文件的 contig ID xxx length xxx 部分会有成千上万个 contig 将这个文件加载到 IGV 时 IGV 会去解析 VCF 这将会是非常缓慢的过程 最好的策略就是只提取其 ID xxx length xxx

    2025年6月2日
    5
  • java将字符串转换为json对象的方法_java jsonobject转string

    java将字符串转换为json对象的方法_java jsonobject转string在与服务器交互的时候,我们往往会使用json字符串,今天的例子是java对象转化为字符串,代码如下protectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Persionp1=newPersion(…

    2026年2月6日
    4
  • 基于xxx的系统实现「建议收藏」

    基于xxx的系统实现「建议收藏」帮助解答任何系统问题1.成品:看最下面2.基于强化学习的Tic-Tac-To实现3.基于文本的关键词打标4.基于自然语言处理的情感分析系统5.基于深度学习的语音识别系统6.基于深度学习的人脸识别系统7.随机森林的多分类问题研究8.回归算法预测系统9.决策树算法的分类系统10.基于Python的lstm情感分析11.基于Python的金融分析系统12.基于Python的电商评论爬虫系统13.基于Flask的校园课程管理系统设计与实现14.基于Flask的人脸识别企业系统15.vb

    2025年12月10日
    3
  • linux 进程监控和自动重启的简单实现(转)

    linux 进程监控和自动重启的简单实现(转)

    2021年9月8日
    62

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号