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)
上一篇 2022年4月16日 上午11:00
下一篇 2022年4月16日 上午11:20


相关推荐

  • data单复数一样吗_Data和media的复数是什么?——别以为你很懂复数!

    data单复数一样吗_Data和media的复数是什么?——别以为你很懂复数!data 和 media 的复数是什么 datas medias 答案是 都错 data 和 media 本身就是复数形式 它们的单数分别是 datum 和 medium 我们都知道 英语单数变复数的规则是大体上是单数名词词尾加 s 构成复数 那么这次我们专门讲不规则的变化 尤其是外来词的单数如何变成复数 结尾为 f y 和 o 的单词 相信大家都比较熟悉 所以这些单词的复数变化 这里也不再赘述 沿袭古英语的变格方

    2026年3月19日
    2
  • pytest测试框架和unittest_python列表生成式

    pytest测试框架和unittest_python列表生成式一、核心要素(1)TestCase测试用例一个.py脚本就是一个测试用例测试用例类必须继承于unittest.TestCase类中的方法名必须以test开头,否则不会被执行类的外部写main方法(自测代码)(2)TestSuite测试套件测试套件就是测试用例的集合把多个测试用例集合到一起就构成了测试套件测试套件不能直接执行(3)TextTestR…

    2022年10月14日
    4
  • CTK插件框架学习3-第一个插件编写

    CTK插件框架学习3-第一个插件编写前两章把CTK插件库编译好了,这里篇编写一个插件试一下,共需要创建两个小工程,一个是插件库,一个是测试程序。1.插件库编写1.1创建工程打开Qtcreator,新建一个EmputyqmakeProject,并给工程命名为ctk-plugin-first。Kits选择”DesktopQt5.12.3MSVC201764bit”。更改ctk-plugin-first.pro文…

    2022年5月18日
    45
  • OpenClaw范式跃迁:当 170+ API 注入RHClaw ,Agent 正式跨入多模态时代

    OpenClaw范式跃迁:当 170+ API 注入RHClaw ,Agent 正式跨入多模态时代

    2026年3月16日
    2
  • LayUI树形表格treetable使用详解[通俗易懂]

    LayUI树形表格treetable使用详解[通俗易懂]LayUI是现在比较流行的一款前端框架,也有很多人基于LayUI开发了很多不错的组件,比如treetable树形表格。因为treetable是第三方基于LayUI开发的,所以需要先用Layui引入一下文件。layui.config({base:’static/layui/’}).extend({treetable:’treetable-lay/treetab…

    2022年6月13日
    304
  • 360浏览器如何设置默认极速模式

    360浏览器如何设置默认极速模式360 浏览器有双核模式 当是极速模式时 使用的内核是 webkit 当是兼容模式时 取决于用户安装的 ie 浏览器的版本 即当安装的是 ie 版本是 ie8 的时候 这个时候 360 浏览器使用的是 ie8 内核 使用 meta 标签 nbsp lt metaname renderer content webkit gt nbsp 注意要加 gt 并且 gt 前要有个空格如果不行 加上 h5 规范 lt DO

    2026年3月18日
    2

发表回复

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

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