maven
<!--使用AspectJ方式注解需要相应的包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.2.5</version>
</dependency>
spring-mybatis.xml
<!-- 配置读数据源 -->
<bean id="READ" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="${db.initialSize}"></property>
<!-- 连接池最大数量 -->
<property name="maxActive" value="${db.maxActive}"></property>
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="${db.maxIdle}"></property>
<!-- 连接池最小空闲 -->
<property name="minIdle" value="${db.minIdle}"></property>
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="${db.maxWait}"></property>
<!--验证SQL -->
<property name="validationQuery" value="select 1"></property>
<!-- 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除 -->
<property name="testWhileIdle" value="true"></property>
<!--每5分钟行一次空闲连接回收器 -->
<property name="timeBetweenEvictionRunsMillis" value="300000"></property>
<!--池中的连接空闲30分钟后被回收 -->
<property name="minEvictableIdleTimeMillis" value="18000000"></property>
<!-- 获取连接时不要测试,否则很影响性能 -->
<property name="testOnBorrow" value="true"></property>
</bean>
<!-- 配置写数据源 -->
<bean id="WRITE" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="${db.initialSize}"></property>
<!-- 连接池最大数量 -->
<property name="maxActive" value="${db.maxActive}"></property>
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="${db.maxIdle}"></property>
<!-- 连接池最小空闲 -->
<property name="minIdle" value="${db.minIdle}"></property>
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="${db.maxWait}"></property>
<!--验证SQL -->
<property name="validationQuery" value="select 1"></property>
<!-- 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除 -->
<property name="testWhileIdle" value="true"></property>
<!--每5分钟行一次空闲连接回收器 -->
<property name="timeBetweenEvictionRunsMillis" value="300000"></property>
<!--池中的连接空闲30分钟后被回收 -->
<property name="minEvictableIdleTimeMillis" value="18000000"></property>
<!-- 获取连接时不要测试,否则很影响性能 -->
<property name="testOnBorrow" value="true"></property>
</bean>
<!-- 配置多数据源映射关系 -->
<bean id="dataSource" class="com.leo.ows.util.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="READ" value-ref="READ"></entry>
<entry key="WRITE" value-ref="WRITE"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="READ"/>
</bean>
<!-- 默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强。-->
<aop:aspectj-autoproxy />
DataSourceHolder .java
package com.leo.ows.util;
/**
* 数据源操作
* @author leo
*/
public class DataSourceHolder {
//线程本地环境
private static final ThreadLocal<String> dataSources = new ThreadLocal<String>();
public static final String DATA_SOURCE_WRITE = "WRITE";
public static final String DATA_SOURCE_READ = "READ";
//设置数据源
public static void setDataSource(String customerType) {
dataSources.set(customerType);
}
//获取数据源
public static String getDataSource() {
return (String) dataSources.get();
}
//清除数据源
public static void clearDataSource() {
dataSources.remove();
}
}
DynamicDataSource.java
package com.leo.ows.util;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 获取数据源(依赖于spring)
* @author
*
* AbstractRoutingDataSource:抽象javax.sql。将getConnection()调用路由到基于查找键的多个目标数据源的数据源实现。后者通常(但不一定)通过某些线程绑定的事务上下文来确定。
*/
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
System.out.println(" ====================获取数据源=======================");
return DataSourceHolder.getDataSource();
}
}
DynamicDataSourceAspect .java
package com.leo.ows.util;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
//指定切面的优先级,当有多个切面时,数值越小优先级越高
@Order(-1)
//把这个类声明为一个切面:需要把该类放入到IOC容器中。再声明为一个切面.
@Aspect
@Component
public class DynamicDataSourceAspect {
@Pointcut("execution (* com.leo.ows.dao.*.select*(..)) || execution (* com.leo.ows.dao.*.count*(..)) ")
public void readMethodPointcut() {}
@Pointcut("execution (* com.leo.ows.dao.*.*(..))")
public void writeMethodPointcut() {}
@Before("readMethodPointcut()")
public void switchReadDataSource(){
System.out.println("============切换到读数据源===========");
DataSourceHolder.setDataSource(DataSourceHolder.DATA_SOURCE_READ);
}
@Before("writeMethodPointcut()")
public void switchWriteDataSource(){
System.out.println("=============切换到写数据源==========");
DataSourceHolder.setDataSource(DataSourceHolder.DATA_SOURCE_WRITE);
}
}
ArticleAction .java
package com.leo.ows.action;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.leo.ows.entity.Article;
import com.leo.ows.servise.ArticleServise;
@Controller
public class ArticleAction {
@Resource
private ArticleServise articleServise;
@RequestMapping(value="/articleAdd",method=RequestMethod.POST)
public String ArticleAdd(Model model,Article article){
System.out.println(article.getTitle());
articleServise.AddArticle(article);
return "index";
}
}
效果图