1.创建一个类,使用注解的形式,方便使用,该注解使用在Service层
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
String value();
}
2.创建一个切面方法,用于拦截所有的Service方法的调用,分配数据源
public class DataSourceAspect {
/**
* 拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源
*
* @param point
* @throws Exception
*/
public void intercept(JoinPoint point) throws Exception {
Class<?> target = point.getTarget().getClass();
MethodSignature signature = (MethodSignature) point.getSignature();
// 默认使用目标类型的注解,如果没有则使用其实现接口的注解
for (Class<?> clazz : target.getInterfaces()) {
resolveDataSource(clazz, signature.getMethod());
}
resolveDataSource(target, signature.getMethod());
}
/**
* 提取目标对象方法注解和类型注解中的数据源标识
*
* @param clazz
* @param method
*/
private void resolveDataSource(Class<?> clazz, Method method) {
try {
Class<?>[] types = method.getParameterTypes();
// 默认使用类型注解
if (clazz.isAnnotationPresent(DataSource.class)) {
DataSource source = clazz.getAnnotation(DataSource.class);
DynamicDataSourceHolder.setDataSource(source.value());
}
// 方法注解可以覆盖类型注解
Method m = clazz.getMethod(method.getName(), types);
if (m != null && m.isAnnotationPresent(DataSource.class)) {
DataSource source = m.getAnnotation(DataSource.class);
DynamicDataSourceHolder.setDataSource(source.value());
}
} catch (Exception e) {
System.out.println(clazz + ":" + e.getMessage());
}
}
}
3.
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
// 从自定义的位置获取数据源标识
return DynamicDataSourceHolder.getDataSource();
}
}
4.
public class DynamicDataSourceHolder {
/**
* 注意:数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰
*/
private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal<String>();
/**
* 配置mysql数据源
*/
public static final String mysql="mysql";
/**
* 配置oracle数据源
*/
public static final String oracle="oracle";
/**
* 配置sqlServer数据源
*/
public static final String sqlServer="sqlServer";
public static String getDataSource() {
return THREAD_DATA_SOURCE.get();
}
public static void setDataSource(String dataSource) {
THREAD_DATA_SOURCE.set(dataSource);
}
public static void clearDataSource() {
THREAD_DATA_SOURCE.remove();
}
}
5.配置配置文件
dbconfig.properties 把数据源信息储存到配置文件中,也可以配在spring-application中
url:jdbc:mysql://localhost:3306/parkmanager?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
driverClassName:com.mysql.jdbc.Driver
username:root
password:ok
filters:stat
maxActive:20
initialSize:1
maxWait:60000
minIdle:10
maxIdle:15
timeBetweenEvictionRunsMillis:60000
minEvictableIdleTimeMillis:300000
validationQuery:SELECT 'x'
testWhileIdle:true
testOnBorrow:false
testOnReturn:false
maxOpenPreparedStatements:20
removeAbandoned:true
removeAbandonedTimeout:1800
logAbandoned:true
ApplicationContext-dataSource.xml 一个对数据源操作的配置文件
<!-- 阿里 druid数据库连接池 -->
<bean />
</bean>
多个数据源 把上面的配置复制粘贴就好
把所有数据源放在一个容器中方便sqlsession管理
<bean />
</bean>
配置sqlsession管理
<!-- sql会话模版 -->
<!--这里使用的是sqlSessionTemplate,也可以不实用,具体情况分析-->
<bean ></property>
</bean>
配置事务管理器
<!-- 拦截所有service层 同一走自定义的dataSourceAspect -->
<bean />
</aop:aspect>
</aop:config>
使用方法
@Service("userService") //service调用
@DataSource(value=DynamicDataSourceHolder.mysql) //选择mysql数据库
public class UserService implements UserManager{
}