上文已经讲了单个数据源的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);
}