Java ssm多数据源协同配置

来源:互联网 发布:stc单片机元件库 编辑:程序博客网 时间:2024/05/22 10:27


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

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

A.driver=com.mysql.jdbc.DriverA.url=jdbc:mysql://127.0.0.1:3306/...?useUnicode=true&characterEncoding=utf8&useSSL=falseA.username=...A.password=...#----------------------B servers--------------------------#B.driver=com.mysql.jdbc.DriverB.url=jdbc:mysql://localhost:3306/...?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=falseB.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 {@Overrideprotected 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@Componentpublic 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的地方,就必须要加了


原创粉丝点击