SSM java切换数据源 实现读写分离

来源:互联网 发布:淘宝刷到一天能赚多少 编辑:程序博客网 时间:2024/06/08 05:58
jar包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</dependency>
配置数据源
<bean id="db1" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
<property name="driverClassName" value="${jdbc.driver}" />

<!-- 基本属性 url、user、password -->
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />

<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${jdbc.pool.init}" />
<property name="minIdle" value="${jdbc.pool.minIdle}" />
<property name="maxActive" value="${jdbc.pool.maxActive}" />

<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000" />

<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />

<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />

<property name="validationQuery" value="${jdbc.testSql}" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
</bean>

实现AbstractRoutingDataSource类 作为数据源

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

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        String dbKey=DataSourceHolder.getDataSources();
        return dbKey;
    }
}

用ThreadLcoal管理当前数据源
public class DataSourceHolder {
    private static final ThreadLocal<String> dataSources = new ThreadLocal<String>();

    public static void setDataSources(String dataSource) {
        dataSources.set(dataSource);
    }

    public static String getDataSources() {
        return dataSources.get();
    }
}

AOP支持
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 动态切换数据源切面
 */
@Component
@Aspect
@Order(-1)
public class DynamicDataSourceInterceptor {

    @Around(value = "@annotation(switchDB)")
    public Object process(ProceedingJoinPoint point, SwitchDB switchDB) throws Throwable {
        Object returnValue;
        try {
            DataSourceHolder.setDataSources(switchDB.dbID());
            returnValue = point.proceed(point.getArgs());
        } finally {
            DataSourceHolder.setDataSources(null);
        }

        return returnValue;
    }
}

注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 动态切换数据源
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SwitchDB {

    String dbID();
}

在spring里面扫描
<aop:aspectj-autoproxy proxy-target-class="true" />
<context:component-scan base-package="cn.zj.pubinfo.comm.mybatis.spring.dynamicdb"><!-- base-package 
如果多个,用“,”分隔 -->
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>

在service层方法中添加注解
@SwitchDB(dbID = "db1") 
public List<String> find() {
return userDao.find();
}
db1已经在数据源配置中配置
现在即可以切换数据源进行操作了。
原创粉丝点击