上文已经讲了单个数据源的Druid的配置

Druid动态数据源配置 主要是继承AbstractRoutingDataSource再通过AOP来实现动态数据源切换

基于原先的程序调整)

 使用步骤:

1.调整配置属性文件:mybatis.properties (增加DataSource连接参数)

1 master.driver=com.mysql.jdbc.Driver
 2 master.url=jdbc:mysql://127.0.0.1:3306/jawavesys
 3 master.username=root
 4 master.password=jawave88
 5 #定义初始连接数
 6 master.initialSize=0
 7 #定义最大连接数
 8 master.maxActive=20
 9 #定义最大空闲
10 master.maxIdle=20
11 #定义最小空闲
12 master.minIdle=1
13 #定义最长等待时间
14 master.maxWait=60000
15 
16 
17 slave.driver=com.mysql.jdbc.Driver
18 slave.url=jdbc:mysql://127.0.0.1:3306/jawave_eform
19 slave.username=root
20 slave.password=jawave88
21 #定义初始连接数
22 slave.initialSize=0
23 #定义最大连接数
24 slave.maxActive=20
25 #定义最大空闲
26 slave.maxIdle=20
27 #定义最小空闲
28 slave.minIdle=1
29 #定义最长等待时间
30 slave.maxWait=60000

2.调整SPRING配置文件:spring-base.xml

1 <?xml version="1.0" encoding="UTF-8"?>
  2 <beans xmlns="http://www.springframework.org/schema/beans"
  3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
  4        xmlns:context="http://www.springframework.org/schema/context"
  5        xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
  6        xmlns:aop="http://www.springframework.org/schema/aop"
  7        xsi:schemaLocation="http://www.springframework.org/schema/beans
  8                         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
  9                         http://www.springframework.org/schema/context  
 10                         http://www.springframework.org/schema/context/spring-context-3.1.xsd  
 11                         http://www.springframework.org/schema/tx
 12                         http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
 13                         http://www.springframework.org/schema/aop 
 14                         http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
 15                         http://www.springframework.org/schema/mvc  
 16                         http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
 17 
 18 
 19     <context:component-scan base-package="com.goku.druid.demo">
 20         <context:exclude-filter type="annotation"
 21                                 expression="org.springframework.stereotype.Controller" />
 22     </context:component-scan>
 23 
 24     <!-- 引入配置文件 -->
 25     <bean id="propertyConfigurer"
 26           class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
 27         <property name="location" value="classpath:mybatis.properties" />
 28     </bean>
 29 
 30     <bean id="masterDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
 31         <property name="driverClassName" value="${master.driver}" />
 32         <property name="url" value="${master.url}" />
 33         <property name="username" value="${master.username}" />
 34         <property name="password" value="${master.password}" />
 35         <!-- 初始化连接大小 -->
 36         <property name="initialSize" value="${master.initialSize}"></property>
 37         <!-- 连接池最大数量 -->
 38         <property name="maxActive" value="${master.maxActive}"></property>
 39         <!-- 连接池最大空闲 -->
 40         <property name="maxIdle" value="${master.maxIdle}"></property>
 41         <!-- 连接池最小空闲 -->
 42         <property name="minIdle" value="${master.minIdle}"></property>
 43         <!-- 获取连接最大等待时间 -->
 44         <property name="maxWait" value="${master.maxWait}"></property>
 45         <!-- 这里配置提交方式,默认就是TRUE,可以不用配置 -->
 46         <property name="defaultAutoCommit" value="true" />
 47         <!-- 验证连接有效与否的SQL,不同的数据配置不同 -->
 48         <property name="validationQuery" value="select 1 " />
 49         <!--通过别名的方式配置扩展插件,监控统计用的filter:stat  日志用的filter:log4j  防御sql注入的filter:wall-->
 50         <property name="filters" value="stat,log4j" />
 51         <property name="proxyFilters">
 52             <list>
 53                 <ref bean="stat-filter" />
 54                 <ref bean="log-filter"/>
 55             </list>
 56         </property>
 57     </bean>
 58 
 59     <bean id="slaveDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
 60         <property name="driverClassName" value="${slave.driver}" />
 61         <property name="url" value="${slave.url}" />
 62         <property name="username" value="${slave.username}" />
 63         <property name="password" value="${slave.password}" />
 64         <!-- 初始化连接大小 -->
 65         <property name="initialSize" value="${slave.initialSize}"></property>
 66         <!-- 连接池最大数量 -->
 67         <property name="maxActive" value="${slave.maxActive}"></property>
 68         <!-- 连接池最大空闲 -->
 69         <property name="maxIdle" value="${slave.maxIdle}"></property>
 70         <!-- 连接池最小空闲 -->
 71         <property name="minIdle" value="${slave.minIdle}"></property>
 72         <!-- 获取连接最大等待时间 -->
 73         <property name="maxWait" value="${slave.maxWait}"></property>
 74         <!-- 这里配置提交方式,默认就是TRUE,可以不用配置 -->
 75         <property name="defaultAutoCommit" value="true" />
 76         <!-- 验证连接有效与否的SQL,不同的数据配置不同 -->
 77         <property name="validationQuery" value="select 1 " />
 78         <!--通过别名的方式配置扩展插件,监控统计用的filter:stat  日志用的filter:log4j  防御sql注入的filter:wall-->
 79         <property name="filters" value="stat,log4j" />
 80         <property name="proxyFilters">
 81             <list>
 82                 <ref bean="stat-filter" />
 83                 <ref bean="log-filter"/>
 84             </list>
 85         </property>
 86     </bean>
 87 
 88     <bean id="dataSource" class="com.goku.druid.demo.util.DynamicDataSource">
 89         <property name="targetDataSources">
 90             <map key-type="java.lang.String">
 91                 <!-- master -->
 92                 <entry key="master" value-ref="masterDataSource"/>
 93                 <!-- slave -->
 94                 <entry key="slave" value-ref="slaveDataSource"/>
 95             </map>
 96         </property>
 97         <property name="defaultTargetDataSource" ref="masterDataSource"/>
 98     </bean>
 99 
100     <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
101     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
102         <property name="dataSource" ref="dataSource" />
103         <!-- 自动扫描mapping.xml文件 -->
104         <property name="mapperLocations" value="classpath:mapping/**/*.xml"></property>
105     </bean>
106 
107     <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
108     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
109         <property name="basePackage" value="com.goku.druid.demo.mapper" />
110         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
111     </bean>
112 
113     <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
114     <bean id="transactionManager"
115           class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
116         <property name="dataSource" ref="dataSource" />
117     </bean>
118 
119     <!-- 开启事务注解驱动 -->
120     <tx:annotation-driven  transaction-manager="transactionManager"/>
121 
122     <!-- 为业务逻辑层的方法解析@DataSource注解  为当前线程的routeholder注入数据源key -->
123     <bean id="dataSourceAspect" class="com.goku.druid.demo.util.DataSourceAspect" />
124     <aop:config proxy-target-class="true">
125         <aop:aspect id="dataSourceAspect" ref="dataSourceAspect" order="1">
126             <aop:pointcut id="tx" expression="execution(* com.goku.druid.demo.service..*.*(..)) "/>
127             <aop:before pointcut-ref="tx" method="before" />
128         </aop:aspect>
129     </aop:config>
130 
131     <!--监控统计-->
132     <bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
133         <property name="slowSqlMillis" value="10000" />
134         <property name="logSlowSql" value="true" />
135     </bean>
136 
137     <!--日志-->
138     <bean id="log-filter" class="com.alibaba.druid.filter.logging.Log4jFilter">
139         <property name="statementExecutableSqlLogEnable" value="true" />
140     </bean>
141 
142 
143 </beans>

3.接下写AbstractRoutingDataSource继承类

package com.goku.druid.demo.util;

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

/**
 * Created by nbfujx on 2017/10/18.
 */
public class DynamicDataSource extends AbstractRoutingDataSource  {

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceHolder.getDataSource();
    }

}

4.接下来写切面实现类

package com.goku.druid.demo.util;

import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

/**
 *  Created by nbfujx on 2017/10/18.
 */
public class DataSourceAspect {


    /**
     * 在dao层方法之前获取datasource对象之前在切面中获取数据源
     */
    public void before(JoinPoint point)
    {
        Object target = point.getTarget();
        System.out.println(target.toString());
        String method = point.getSignature().getName();
        System.out.println(method);
        Class<?>[] classz = target.getClass().getInterfaces();
        Class<?>[] parameterTypes = ((MethodSignature) point.getSignature())
                .getMethod().getParameterTypes();
        try {
            Method m = classz[0].getMethod(method, parameterTypes);
            System.out.println("method"+ m.getName());
            if (m != null && m.isAnnotationPresent(DataSource.class)) {
                DataSource data = m.getAnnotation(DataSource.class);
                System.out.println("dataSource:"+data.value());
                DataSourceHolder.putDataSource(data.value());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5.还有拿到数据元的类

package com.goku.druid.demo.util;

/**
 * Created by nbfujx on 2017/10/18.
 */
public class DataSourceHolder {
    public static final ThreadLocal<String> holder = new ThreadLocal<String>();

    /**
     * 设置数据源
     */
    public static void putDataSource(String datasource) {
        holder.set(datasource);
    }

    /**
     * 获取数据源
     */
    public static String getDataSource() {
        return holder.get();
    }


    /**
     * 清除数据源
     */
    public static void clearDataSource() {
        holder.remove();
    }
}

6.DataSource数据源注解类

package com.goku.druid.demo.util;


import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Created by nbfujx on 2017/10/18.
 */

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataSource {
    String value();
}

7.在service层进行数据源注解切换

package com.goku.druid.demo.service;

import com.goku.druid.demo.model.FormElement;
import com.goku.druid.demo.model.UserWithBLOBs;
import com.goku.druid.demo.util.DataSource;

/**
 * Created by nbfujx on 2017-10-18.
 */
public interface UserService {
    @DataSource("master")
    UserWithBLOBs selectByPrimaryKey(String id);

    @DataSource("slave")
    FormElement selectByPrimaryKey2(Integer id);
}