Spring+Mybatis 实现aop数据库读写分离与多数据库源配置操作
程序员文章站
2024-02-27 19:22:03
在数据库层面大都采用读写分离技术,就是一个master数据库,多个slave数据库。master库负责数据更新和实时数据查询,slave库当然负责非实时数据查询。因为在实际...
在数据库层面大都采用读写分离技术,就是一个master数据库,多个slave数据库。master库负责数据更新和实时数据查询,slave库当然负责非实时数据查询。因为在实际的应用中,数据库都是读多写少(读取数据的频率高,更新数据的频率相对较少),而读取数据通常耗时比较长,占用数据库服务器的cpu较多,从而影响用户体验。我们通常的做法就是把查询从主库中抽取出来,采用多个从库,使用负载均衡,减轻每个从库的查询压力。
废话不多说,多数据源配置和主从数据配置原理一样
1、首先配置 jdbc.properties 两个数据库 a 和 b
#============ 双数据源 ======# #----------------------a servers--------------------------# a.driver=com.mysql.jdbc.driver a.url=jdbc:mysql://localhost:3619/gps4?useunicode=true&characterencoding=utf8 a.username=gpsadmin a.password=1qaz&619 #----------------------b servers--------------------------# b.driver=com.mysql.jdbc.driver b.url=jdbc:mysql://localhost:3619/gps6?useunicode=true&characterencoding=utf8 b.username=gpsadmin b.password=1qaz&619
2、配置 spring-mybatis.xml 文件【重要】
<!-- 引入配置文件 --> <bean id="propertyconfigurer" class="org.springframework.beans.factory.config.propertyplaceholderconfigurer"> <property name="location" value="classpath:resources/jdbc.properties" /> </bean> <!-- dbcp连接池 --> <!-- <bean id="datasource" class="org.apache.commons.dbcp.basicdatasource" destroy-method="close"> <property name="driverclassname" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> 初始化连接大小 <property name="initialsize" value="${initialsize}"></property> 连接池最大数量 <property name="maxactive" value="${maxactive}"></property> 连接池最大空闲 <property name="maxidle" value="${maxidle}"></property> 连接池最小空闲 <property name="minidle" value="${minidle}"></property> 获取连接最大等待时间 <property name="maxwait" value="${maxwait}"></property> </``> --> <!-- 【重点】 a 数据源 --> <bean name="datasourcea" class="org.springframework.jdbc.datasource.drivermanagerdatasource"> <property name="driverclassname" value="${a.driver}" /> <property name="url" value="${a.url}" /> <property name="username" value="${a.username}" /> <property name="password" value="${a.password}" /> </bean> <!-- 【重点】 b 数据源 --> <bean name="datasourceb" class="org.springframework.jdbc.datasource.drivermanagerdatasource"> <property name="driverclassname" value="${b.driver}" /> <property name="url" value="${b.url}" /> <property name="username" value="${b.username}" /> <property name="password" value="${b.password}" /> </bean> <!--【重点】 双数据源 配合 --> <bean id="datasource" class="com.ifengsearch.common.database.dynamicdatasource"> <property name="defaulttargetdatasource" ref="datasourceb"/> <property name="targetdatasources"> <map> <entry key="datasourcea" value-ref="datasourcea"/> <entry key="datasourceb" value-ref="datasourceb"/> </map> </property> </bean> <!-- 【重点】 加入 aop 自动扫描 datasourceaspect 配置数据库注解aop --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <bean id="manydatasourceaspect" class="com.ifengsearch.common.database.datasourceaspect" /> <aop:config> <!-- 扫描 注解的 数据源 --> <aop:aspect id="c" ref="manydatasourceaspect"> <aop:pointcut id="tx" expression="execution(* com.ifengsearch.*.dao.*.*(..))"/> <aop:before pointcut-ref="tx" method="before"/> </aop:aspect> </aop:config> <!-- 配置数据连接 工厂 自动扫描mapping.xml文件 --> <bean id="sqlsessionfactory" class="org.mybatis.spring.sqlsessionfactorybean"> <property name="datasource" ref="datasource"/> <!-- 自动扫描mapping.xml文件 --> <property name="mapperlocations" value="classpath:com/ifengsearch/*/mapping/*.xml"></property> </bean> <!-- dao接口所在包名,spring会自动查找其下的类 --> <bean class="org.mybatis.spring.mapper.mapperscannerconfigurer"> <property name="basepackage" value="com.ifengsearch.*.dao" /> <property name="sqlsessionfactorybeanname" value="sqlsessionfactory"></property> </bean> <!-- (事务管理)transaction manager, use jtatransactionmanager for global tx 事务 --> <bean id="transactionmanager" class="org.springframework.jdbc.datasource.datasourcetransactionmanager"> <property name="datasource" ref="datasource" /> </bean>
3、编写几个java类动态调用数据源【重要】
a:自定义一个注解,负责动态调用数据源
package com.ifengsearch.common.database; import java.lang.annotation.*; /** * 设置 数据源 注解标签的用法 写上注解标签, * 调用相应方法切换数据源咯(就跟你设置事务一样) * 【也可以配置 主从数据库】 * * @author flm * @2017年9月12日 */ @retention(retentionpolicy.runtime) @target(elementtype.method) public @interface datasource { public static string datasourcea = "datasourcea"; // a数据源 public static string datasourceb = "datasourceb"; // b数据源 string value(); }
b、数据源的获取 object aop实现 (反射)
package com.ifengsearch.common.database; import java.lang.reflect.method; import org.apache.log4j.logger; import org.aspectj.lang.joinpoint; import org.aspectj.lang.reflect.methodsignature; /** * 数据源的获取 * aop实现 (反射) * @author flm * @2017年9月12日 */ public class datasourceaspect{ private logger log = logger.getlogger(datasourceaspect.class); public void before(joinpoint point) { object target = point.gettarget();// 拦截的实体类 string method = point.getsignature().getname();// 拦截的方法名称 class<?>[] classz = target.getclass().getinterfaces(); class<?>[] parametertypes = ((methodsignature) point.getsignature()) .getmethod().getparametertypes();// 拦截的方法参数类型 try { method m = classz[0].getmethod(method, parametertypes); if (m != null && m.isannotationpresent(datasource.class)) { datasource data = m .getannotation(datasource.class); datasourceholder.setdatasource(data.value()); log.info("数据源的获取 datasource: "+data.value()); } } catch (exception e) { log.error("数据源的获取 aop实现 出错:"+e.getmessage()); } } }
c、datasourceholder 数据源操作 获取数据源 帮助类
package com.ifengsearch.common.database; /** * 多数据源 * 数据源操作 获取数据源 * @author flm * @2017年9月12日 */ public class datasourceholder { //线程本地环境 private static final threadlocal<string> datasources = new threadlocal<string>(); //设置数据源 public static void setdatasource(string customertype) { datasources.set(customertype); } //获取数据源 public static string getdatasource() { return (string) datasources.get(); } //清除数据源 public static void cleardatasource() { datasources.remove(); } }
d、 我们还需要实现spring的抽象类abstractroutingdatasource,就是实现determinecurrentlookupkey方法:
package com.ifengsearch.common.database; import org.springframework.jdbc.datasource.lookup.abstractroutingdatasource; /** * 多数据源 * 获取数据源(依赖于spring) * @author flm * @2017年9月12日 */ public class dynamicdatasource extends abstractroutingdatasource{ @override protected object determinecurrentlookupkey() { return datasourceholder.getdatasource(); } }
4、接下来就可以看结果了
我在dao层直接调用
public interface userdao { /** * 登录判断 【数据源b】 */ @datasource(value=datasource.datasourceb) public list<userbean> getloginuserlist(@param("loginname")string loginname,@param("loginpwd")string loginpwd); /** * 查找上一级 服务商 【数据源a】 */ @datasource(value=datasource.datasourcea) public userbean getserveruser(@param("u_last_id")integer u_last_id); }
总结
以上所述是小编给大家介绍的spring+mybatis 实现aop数据库读写分离与多数据库源配置操作,希望对大家有所帮助
上一篇: php强制下载文件函数
下一篇: 完整版银行ATM机的实现