Java ssm多数据源协同配置


项目中需要用到连个数据源的连接,分别在两个不同的服务器上,地址不同,各自所负责的工作也不同,所以用到了aop的形式配置多数据源的形式,并且加入了注解

1、首先写一下jdbc的配置连接文件,我用的连个都是mysql数据库,其他类型的库也是一样的

A.driver=com.mysql.jdbc.Driver
A.url=jdbc:mysql://127.0.0.1:3306/...?useUnicode=true&characterEncoding=utf8&useSSL=false
A.username=...
A.password=...
#----------------------B servers--------------------------#
B.driver=com.mysql.jdbc.Driver
B.url=jdbc:mysql://localhost:3306/...?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false
B.username=...
B.password=...





#初始化连接大小
jdbc.initialSize=10
#连接池最大数量
jdbc.maxActive=100
#连接池最大空闲
jdbc.maxIdle=1800
#获取连接最大等待时间
jdbc.maxWait=30000
#连接池最小空闲 
jdbc.minIdle=20

2.因为我是吧Spring的配置文件和mybatis的配置文件写到一起的,所以就一起展示

spring-mybatis.xml引入aop基本配置

xmlns:aop="http://www.springframework.org/schema/aop"

 http://www.springframework.org/schema/aop  
                        http://www.springframework.org/schema/aop/spring-aop.xsd   

在下方加入aop的配置

<aop:aspectj-autoproxy proxy-target-class="false"/>


spring-mybatis.xml引入配置文件

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    <property name="locations">  
        <array>  
            <value>classpath:jdbc.properties</value>
        </array>  
    </property>  
</bean>  
引入多数据源

<bean id="dataSourceA"   
        class="org.apache.commons.dbcp.BasicDataSource">  
        <property name="driverClassName" value="${A.driver}"/>  
        <property name="url" value="${A.url}"/>  
        <property name="username" value="${A.username}"/>  
        <property name="password" value="${A.password}"/>
         <!-- 初始化连接大小 -->  
        <property name="initialSize" value="${jdbc.initialSize}"></property>  
        <!-- 连接池最大数量 -->  
        <property name="maxActive" value="${jdbc.maxActive}"></property>  
        <!-- 连接池最大空闲 -->  
        <property name="maxIdle" value="${jdbc.maxIdle}"></property>  
        <!-- 连接池最小空闲 -->  
        <property name="minIdle" value="${jdbc.minIdle}"></property>  
        <!-- 获取连接最大等待时间 -->  
        <property name="maxWait" value="${jdbc.maxWait}"></property> 
        
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> 
        <property name="minEvictableIdleTimeMillis" value="300000" /> 
        <property name="validationQuery" value="SELECT 'x'" /> 
        <property name="testWhileIdle" value="true" /> 
        <property name="testOnBorrow" value="false" /> 
        <property name="testOnReturn" value="false" />   
    </bean>
    
      
    <bean id="dataSourceB"   
        class="org.apache.commons.dbcp.BasicDataSource">  
        <property name="driverClassName" value="${B.driver}"/>  
        <property name="url" value="${B.url}"/>  
        <property name="username" value="${B.username}"/>  
        <property name="password" value="${B.password}"/> 
         <!-- 初始化连接大小 -->  
        <property name="initialSize" value="${jdbc.initialSize}"></property>  
        <!-- 连接池最大数量 -->  
        <property name="maxActive" value="${jdbc.maxActive}"></property>  
        <!-- 连接池最大空闲 -->  
        <property name="maxIdle" value="${jdbc.maxIdle}"></property>  
        <!-- 连接池最小空闲 -->  
        <property name="minIdle" value="${jdbc.minIdle}"></property>  
        <!-- 获取连接最大等待时间 -->  
        <property name="maxWait" value="${jdbc.maxWait}"></property> 
        
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> 
        <property name="minEvictableIdleTimeMillis" value="300000" /> 
        <property name="validationQuery" value="SELECT 'x'" /> 
        <property name="testWhileIdle" value="true" /> 
        <property name="testOnBorrow" value="false" /> 
        <property name="testOnReturn" value="false" />  
    </bean>  
    
    
<!--  双数据源 配合 -->
 <bean id="dataSource" class="com.firstCapacity.util.aop.ChooseDataSource">
  <property name="defaultTargetDataSource" ref="dataSourceA"/>
  <property name="targetDataSources">
   <map>
    <entry key="A" value-ref="dataSourceA"/>
    <entry key="B" value-ref="dataSourceB"/>
   </map>
  </property>
 </bean>

其他的包结构扫描基本配置都和大家一样,就不多说了,这里双数据源配置的时候用到了aop的自定义扫描类

ChooseDataSource.java

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


public class ChooseDataSource extends AbstractRoutingDataSource {

	@Override
	protected Object determineCurrentLookupKey() {
//		System.out.println("获取到的数据源为:"+HandleDataSource.getDataSource());
		return HandleDataSource.getDataSource();
	}
	
}

DataSourceAspect.java

public class HandleDataSource {
	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();
	}    
}

HandleDataSource.java

public class HandleDataSource {
	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();
	}    
}

自定义的注解:

DataSource.java

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataSource {
	String value() default "A";
}
在mapper层进行直接转换数据源

DataSourceAspect.java

import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class DataSourceAspect {
	@Pointcut("execution(* com.firstCapacity.business.*.mapper..*(..))")  
	public void pointCut(){};  
	
    @Before(value = "pointCut()")
	 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(m.getName());
				if (m != null && m.isAnnotationPresent(DataSource.class)) {
					DataSource data = m.getAnnotation(DataSource.class);
					HandleDataSource.putDataSource(data.value());
				}
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
}

最后,我们开始使用一下

在mapper的接口上加入我们自定义的注解进行测试

//按照名称查询
    @DataSource("A")
    public User getByUsername(String userName);

测试成功,这里默认的是A,也就是说可以不加,但是用到数据源B的地方,就必须要加了


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值