篇十八:SpringMVC整合Mybatis-Proxy
参考博客:http://www.cnblogs.com/liujiduo/p/5004691.html
http://www.cnblogs.com/surge/p/3582248.html
一、概览
1、在Linux中配置数据库主从复制、读写分离;
2、SpringMVC整合数据库,通过注解实现读写分离
二、整合
1、配置多个数据源(主库、从库),jdbc.properties文件也对应配置多个数据源的连接消息
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 主库:基于Druid数据库链接池的数据源配置 --> <bean id="masterDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!-- 基本属性driverClassName、 url、user、password --> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="${master.url}" /> <property name="username" value="${master.username}" /> <property name="password" value="${master.password}" /> <!-- 配置初始化大小、最小、最大 --> <!-- 通常来说,只需要修改initialSize、minIdle、maxActive --> <property name="initialSize" value="2" /> <property name="minIdle" value="2" /> <property name="maxActive" value="30" /> <property name="testWhileIdle" value="false" /> <!-- 配置获取连接等待超时的时间 --> <property name="maxWait" value="5000" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="30000" /> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 解密密码必须要配置的项 --> <property name="filters" value="config" /> <property name="connectionProperties" value="config.decrypt=false" /> </bean> <!-- 从库 --> <bean id="slaveDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!-- 基本属性driverClassName、 url、user、password --> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="${slave.url}" /> <property name="username" value="${slave.username}" /> <property name="password" value="${slave.password}" /> <!-- 配置初始化大小、最小、最大 --> <!-- 通常来说,只需要修改initialSize、minIdle、maxActive --> <property name="initialSize" value="2" /> <property name="minIdle" value="2" /> <property name="maxActive" value="30" /> <property name="testWhileIdle" value="false" /> <!-- 配置获取连接等待超时的时间 --> <property name="maxWait" value="5000" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="30000" /> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 解密密码必须要配置的项 --> <property name="filters" value="config" /> <property name="connectionProperties" value="config.decrypt=false" /> </bean> <!-- 动态分配数据库连接源 --> <bean id="dynamicDataSource" class="com.common.core.dao.proxy.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="masterDataSource" value-ref="masterDataSource"></entry> <entry key="slaveDataSource" value-ref="slaveDataSource"></entry> </map> </property> <property name="defaultTargetDataSource" ref="masterDataSource" /> </bean> <!-- SqlSession模板类实例 --> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype" destroy-method="close"> <constructor-arg index="0" ref="sqlSessionFactory" /> </bean> <!-- 将数据源映射到sqlSessionFactory中 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="configLocation" value="classpath:mybatis/mybatis-config.xml" /> <property name="dataSource" ref="dynamicDataSource" /> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageHelper"> <property name="properties"> <value> dialect=hsqldb </value> </property> </bean> </array> </property> </bean> <!--======= 事务配置 Begin ================= --> <!-- 事务管理器(由Spring管理MyBatis的事务) --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 关联数据源 --> <property name="dataSource" ref="dynamicDataSource"></property> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <!--======= 事务配置 End =================== --> <!-- 读取数据库配置文件 --> <context:property-placeholder location="/jdbc.properties"/> <!-- 配置切面 --> <bean id="dataSourceAspect" class="com.common.core.dao.proxy.DataSourceAspect" /> <aop:config> <aop:aspect ref="dataSourceAspect"> <aop:pointcut id="dataSourcePointcut" expression="execution(* com.common.dao..*(..))"/> <aop:before pointcut-ref="dataSourcePointcut" method="intercept"/> </aop:aspect> </aop:config> </beans>
jdbc.properties
#mysql数据库 #db.dbType=mysql jdbcDriverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/common?useUnicode=true&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&rewriteBatchedStatements=true jdbc.username=root jdbc.password=abcd%1234 #######读写分离配置连接 master.url=jdbc:mysql://192.168.1.86:3306/test?useUnicode=true&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&rewriteBatchedStatements=true master.username=root master.password=life%1234 slave.url=jdbc:mysql://192.168.1.59:3306/test?useUnicode=true&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&rewriteBatchedStatements=true slave.username=root slave.password=life%1234
2、创建DynamicDataSource类,继承AbstractRoutingDataSource
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /** * * @author liuguangping * 调用DynamicDataSourceHolder,获取配置的数据源 */ public class DynamicDataSource extends AbstractRoutingDataSource{ @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceHolder.getDataSource(); } }
3、创建DynamicDataSourceHolder,动态修改当前数据库连接源
package com.common.core.dao.proxy; /** * * @author liuguangping * */ public class DynamicDataSourceHolder { /** * 设置线程 */ public static final ThreadLocal<String> holder = new ThreadLocal<String>(); /** * 设置连接源 * @param name */ public static void putDataSource(String name){ holder.set(name); } /** * 获取连接源 * @return */ public static String getDataSource(){ return holder.get(); } }
4、创建DataSourceAspect,通过AOP在执行数据库操作时,动态配置数据源
package com.common.core.dao.proxy; import java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.MethodSignature; import com.common.core.dao.proxy.annotation.DataSource; /** * aop切面,拦截所有DaoImpl的方法 * @author liuguangping * */ public class DataSourceAspect { public void intercept(JoinPoint point) throws Exception{ Class<?> target = point.getTarget().getClass(); MethodSignature signnature = (MethodSignature) point.getSignature(); for(Class<?> clazz : target.getInterfaces()){ resolveDataSource(clazz, signnature.getMethod()); } resolveDataSource(target, signnature.getMethod()); } private void resolveDataSource(Class<?> clazz,Method method) { try { Class<?>[] types = method.getParameterTypes(); if(clazz.isAnnotationPresent(DataSource.class)) { DataSource source = clazz.getAnnotation(DataSource.class); DynamicDataSourceHolder.putDataSource(source.value()); } //方法注解可以覆盖类型注解 Method m = clazz.getMethod(method.getName(), types); if(m != null && m.isAnnotationPresent(DataSource.class)) { DataSource source = m.getAnnotation(DataSource.class); DynamicDataSourceHolder.putDataSource(source.value()); } } catch (Exception e) { e.printStackTrace(); } } }
5、创建注解DataSource
package com.common.core.dao.proxy.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface DataSource { String value(); }

浙公网安备 33010602011771号