springmvc mybatis aop 读写分离 代码实现

关于项目配置,以前的博客都有,我就不多提了,我只发有差异的地方

package com.fileServer.datasource;

import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;



/**
 * Created by creekhan on 6/13/16.
 */
@Aspect
@Order(value = -9999)
@Component
public class DynamicDataSourceAop {

	private static final Logger LOGGER = LoggerFactory.getLogger(DynamicDataSourceAop.class);
	
    private static final String[] slaveMethodPreix = {"get", "query", "find", "select", "count","page","isContain","list","check"};
    
    @Before(" execution( * com.fileServer.serviceimpl..*.*(..) ) or  execution( * com.appcore.service.impl.*.*(..) ) ")
    public void checkTransaction(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        if (StringUtils.startsWithAny(methodName, slaveMethodPreix)) {
        	LOGGER.info("当前方法名【{}】切换的数据源【{}】",new Object[] { methodName,"SLAVE"});
        	DynamicDataSourceHolder.setDataSourceKey(DynamicDataSourceHolder.DataSoureKey.SLAVE);	
         } else {
        	LOGGER.info("当前方法名【{}】切换的数据源【{}】",new Object[] { methodName,"MASTER"});
            DynamicDataSourceHolder.setDataSourceKey(DynamicDataSourceHolder.DataSoureKey.MASTER);
        }
    }
    
    
}

package com.fileServer.datasource;



/**
 * Created by creekhan on 6/13/16.
 */
public class DynamicDataSourceHolder {

    private static final ThreadLocal<DataSoureKey> dataSoureThreadLocal = new ThreadLocal<>();

    public static String getDataSourceKey() {
        String persisName = "";
        DataSoureKey dataSoureKey = dataSoureThreadLocal.get();
        if (dataSoureKey == null) {
            persisName = DataSoureKey.MASTER.getKey();
        } else {
            persisName = dataSoureKey.getKey();
        }
        return persisName;
    }

    public static void setDataSourceKey(DataSoureKey dataSource) {
        dataSoureThreadLocal.set(dataSource);
    }


    public static enum DataSoureKey {
        MASTER {
            @Override
            String getKey() {
                return DATASOURCE_MASTER;
            }
        }, SLAVE {
            @Override
            String getKey() {
                return DATASOURCE_SALVE;
            }
        }, ADS {
            @Override
            String getKey() {
                return DATASOURCE_ADS;
            }
        };

        private static final String DATASOURCE_MASTER = "master";
        private static final String DATASOURCE_SALVE = "slave";
        private static final String DATASOURCE_ADS = "ads";

        abstract String getKey();

    }

}

package com.fileServer.datasource;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * Created by creekhan on 6/13/16.
 */
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {

        String key = DynamicDataSourceHolder.getDataSourceKey();
        return key;
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
			http://www.springframework.org/schema/beans 
			http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        	http://www.springframework.org/schema/context
        	http://www.springframework.org/schema/context/spring-context-4.1.xsd
        	">
        	
    <!-- 加载配置 -->
	<context:property-placeholder location="classpath:jdbc.properties" ignore-unresolvable="true" />
	
	
	<!-- 创建数据源 -->
    <bean id="masterDataSource" class="com.alibaba.druid.pool.DruidDataSource" >
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="maxActive" value="${pool.maxPoolSize}" />
        <!-- 超过时间限制是否回收 -->
        <property name="removeAbandoned" value="true" />
        <!-- 超时时间;单位为秒。180秒=3分钟 -->
        <property name="removeAbandonedTimeout" value="${pool.removeAbandonedTimeout}" />
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="${pool.maxWait}" />
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="${pool.timeBetweenEvictionRunsMillis}" />
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="${pool.minEvictableIdleTimeMillis}" />
        <property name="validationQuery" value="${pool.validationQuery} " />
        <property name="testWhileIdle" value="true" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
    </bean>
    
    
    <!-- 创建数据源 -->
    <bean id="slaveDataSource" class="com.alibaba.druid.pool.DruidDataSource" >
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url2}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="maxActive" value="${pool.maxPoolSize}" />
        <!-- 超过时间限制是否回收 -->
        <property name="removeAbandoned" value="true" />
        <!-- 超时时间;单位为秒。180秒=3分钟 -->
        <property name="removeAbandonedTimeout" value="${pool.removeAbandonedTimeout}" />
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="${pool.maxWait}" />
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="${pool.timeBetweenEvictionRunsMillis}" />
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="${pool.minEvictableIdleTimeMillis}" />
        <property name="validationQuery" value="${pool.validationQuery} " />
        <property name="testWhileIdle" value="true" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
    </bean>
    
    <bean id="daynamicDataSource" class="com.fileServer.datasource.DynamicRoutingDataSource">
        <property name="targetDataSources">
            <map key-type="java.lang.String">
                <entry key="master" value-ref="masterDataSource"/>
                <entry key="slave" value-ref="slaveDataSource"/>
            </map>
        </property>
    </bean>
		
	
</beans>



核心思路:先初始化多个数据源的bean,然后通过AOP切面切换数据库对应的key(这里一定得用ThreadLocal这个类来对多线程的数据源Key做隔离处理)以及继承AbstractRoutingDataSource来实现多数据源的路由,AOP切面获取joinPoint.getSignature().getName()方法名,再根据自定义的规则做相应的处理。数据库master只允许写入操作,从库只允许读操作,从库和主库在通过mysql 的binLog日志来实现数据同步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值