1. 程式人生 > >SSM配置多資料來源

SSM配置多資料來源

第一種方法:使用工具類

配置properties檔案

#-----------------oracle 第一個資料來源-------------
datesources.driverClass=oracle.jdbc.driver.OracleDriver
datesources.jdbcUrl=jdbc\:oracle\:thin\:@localhost\:1521\:orcl
datesources.user=test
datesources.password=test
#-----------------oracle 第二個資料來源-------------
datesources2.driverClass=oracle.jdbc.driver.OracleDriver
datesources2.jdbcUrl=jdbc\:oracle\:thin\:@localhost\:1521\:orcl
datesources2.user=tjsfjd
datesources2.password=tjsfjd

配置applicationContext.xml檔案

<!--dbcp是apache的連結池-->
    <!--org.springframework.jdbc.datasource.DriverManagerDataSource使用傳統的jdbc連結方式-->
    <!--第一個資料來源-->
    <bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${datesources.driverClass}"></property>
        <property name="url" value="${datesources.jdbcUrl}"></property>
        <property name="username" value="${datesources.user}"></property>
        <property name="password" value="${datesources.password}"></property>
    </bean>
    <!--第二個資料來源-->
    <bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${datesources2.driverClass}"></property>
        <property name="url" value="${datesources2.jdbcUrl}"></property>
        <property name="username" value="${datesources2.user}"></property>
        <property name="password" value="${datesources2.password}"></property>
    </bean>
    <!--com.my.ssmmaven.util.DataSources 為獲取獲取資料來源類-->
    <bean id="dataSource" class="com.my.ssmmaven.util.DataSources">
             <property name="targetDataSources">
                 <map key-type="java.lang.String">
                    <!-- 指定lookupKey和與之對應的資料來源 -->
                    <entry key="dataSource1" value-ref="dataSource1"></entry>
                   <entry key="dataSource2" value-ref="dataSource2"></entry>
               </map>
             </property>
           <!-- 這裡可以指定預設的資料來源 -->
            <property name="defaultTargetDataSource" ref="dataSource1" />
    </bean>

編碼工具類

1.DataSources

2.DynamicDataSourceHolder

package com.my.ssmmaven.util;

/**
 * @author zhoujq
 * @version 1.0
 * @description
 * @date 2018/7/12 19:55
 * @modified
 */
public class DynamicDataSourceHolder {
    /**
     * 注意:資料來源標識儲存線上程變數中,避免多執行緒操作資料來源時互相干擾
     */
    private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal<String>();

    public static String getDataSource() {
        return THREAD_DATA_SOURCE.get();
    }

    /**
     * 切換資料來源
     * @param dataSource 資料來源
     */
    public static void setDataSource(String dataSource) {
        THREAD_DATA_SOURCE.set(dataSource);
    }

    public static void clearDataSource() {
        THREAD_DATA_SOURCE.remove();
    }
}
package com.my.ssmmaven.util;

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

/**
 * @author zhoujq
 * @version 1.0
 * @description ssm配置多個數據源
 * @date 2018/7/12 19:43
 * @modified
 */
public class DataSources extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        // 從自定義的位置獲取資料來源標識
        return DynamicDataSourceHolder.getDataSource();
    }
}

service層呼叫

package com.my.ssmmaven.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.my.ssmmaven.mapper.IGetTestListMapper;
import com.my.ssmmaven.service.IGetTestListService;
import com.my.ssmmaven.util.DataSources.DataSourcesMenu;
import com.my.ssmmaven.util.DataSources.DynamicDataSourceHolder;
import com.my.ssmmaven.util.TurnPage;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author zhoujq
 * @version 1.0
 * @description
 * @date 2018/7/6 10:52
 * @modified
 */
@Service
public class GetTestListServerImpl implements IGetTestListService{

    @Resource
    IGetTestListMapper getTestListMapper;

    /**
     * 使用預設資料來源
     * @param params
     * @return
     */
    @Override
    public JSONObject getTestList(JSONObject params) {
        JSONObject result = new JSONObject();
        List<JSONObject> list= getTestListMapper.getTestList(params);
        result.put("list",list);
        return result;
    }

    /**
     * 使用第二個資料來源
     * @return
     */
    @Override
    public JSONObject getOrgList() {
        DynamicDataSourceHolder.setDataSource(DataSourcesMenu.TJSFJD.getValue());
        JSONObject result = new JSONObject();
        List<JSONObject> list= getTestListMapper.getOrgList();
        result.put("list",list.get(0));
        return result;
    }
}

第二種方法:使用註解

配置pom.xml,引入依賴

 <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.11</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.11</version>
  </dependency>

配置applicationContext.xml

1.配置資料來源 (省略)

2.配置註解攔截器,aop注入

 <!--配置註解aop及攔截器     class 全類名 -->
    <bean id="dataSourceAspect" class="com.my.ssmmaven.util.AnoDataSources.DataSourceAspect"/>
    <aop:config>
        <aop:aspect ref="dataSourceAspect">
            <!-- 攔截所有service方法 -->
            <aop:pointcut id="dataSourcePointcut" expression="execution(* com.my.ssmmaven.service.*.*(..))"/>
            <aop:before pointcut-ref="dataSourcePointcut" method="intercept"/>
        </aop:aspect>
    </aop:config>

編寫工具類

1.DataSource

2.DataSourceAspect

package com.my.ssmmaven.util.AnoDataSources;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({ TYPE, METHOD })
@Retention(RUNTIME)
public @interface DataSource {
    String value();
}
package com.my.ssmmaven.util.AnoDataSources;

import com.my.ssmmaven.util.DataSources.DynamicDataSourceHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;


/**
 * @author zhoujq
 * @version .
 * @description
 * @date // :
 * @modified
 */
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());
                     }
             }

}

service層呼叫,可在方法名或者類名上使用註解

package com.my.ssmmaven.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.my.ssmmaven.mapper.IGetTestListMapper;
import com.my.ssmmaven.service.IGetTestListService;
import com.my.ssmmaven.util.AnoDataSources.DataSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author zhoujq
 * @version 1.0
 * @description
 * @date 2018/7/6 10:52
 * @modified
 */
@Service
public class GetTestListServerImpl implements IGetTestListService{

    @Resource
    IGetTestListMapper getTestListMapper;

    /**
     * 使用預設資料來源
     * @param params
     * @return
     */
    @Override
    @Transactional
    public JSONObject getTestList(JSONObject params) {
        JSONObject result = new JSONObject();
        List<JSONObject> list= getTestListMapper.getTestList(params);
        result.put("list",list);
        return result;
    }

    /**
     * 使用第二個資料來源
     * @return
     */
    @Override
    @DataSource("dataSource2")
    public JSONObject getOrgList() {
        JSONObject result = new JSONObject();
        List<JSONObject> list= getTestListMapper.getOrgList();
        result.put("list",list.get(0));
        return result;
    }
}