SSM框架,配置多个数据源

6 篇文章 0 订阅
2 篇文章 1 订阅

因为公司需求,不同的接口需要连接不同的数据库,在网上找了些资料,最后解决了这个问题

1.首先在db.properties里配置

#dataSource1
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://XXX:3306/xxx?characterEncoding=utf-8&useSSL=false
jdbc.username=root
jdbc.password=root
#dataSource2
jdbc.driver2=com.mysql.jdbc.Driver
jdbc.url2=jdbc:mysql://XXX:3306/xxx?characterEncoding=utf-8&useSSL=false
jdbc.username2=root
jdbc.password2=root

2.自定义注解

package com.xxx.common;

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

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
    String value();
}

3.拦截解析注解类DataSourceAspect.java

package com.XXX.common;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;


public class DataSourceAspect{
    //	拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源
    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());
    }
    /**
     * 提取目标对象方法注解和类型注解中的数据源标识
     */

    public void resolveDataSource(Class<?>clazz,Method method) {
        try {
            Class<?>[]types=method.getParameterTypes();
//			默认使用类型注解
            if (clazz.isAnnotationPresent(DataSource.class)) {
                DataSource source = clazz.getAnnotation(DataSource.class);
                DbContextHolder.setDataSource(source.value());
            }
//			方法注解可以覆盖类型注解
            Method m=clazz.getMethod(method.getName(), types);
            if (m!=null && m.isAnnotationPresent(DataSource.class)) {
                DataSource source = m.getAnnotation(DataSource.class);
                DbContextHolder.setDataSource(source.value());
            }
        } catch (Exception e) {
            System.out.println(clazz+":"+e.getMessage());
        }
    }
}

4.切换数据库的工具类DbContextHolder.java

package com.xxx.common;


public class DbContextHolder {
	//ThreadLocal是一个本地线程副本变量工具类
    private static final ThreadLocal<String>THREAD_DATA_SOURCE =new ThreadLocal<String>();
    /**
     * 设置当前数据库
     */
    public static void setDataSource(String dataSource) {
        THREAD_DATA_SOURCE.set(dataSource);
    }
    /**
     * 取得当前数据库
     */
    public static String getDataSource() {
        return THREAD_DATA_SOURCE.get();
    }

    /**
     * 清除上下文数据
     */
    public static void clearDataSource() {
        THREAD_DATA_SOURCE.remove();
    }
}

5.自定义动态数据源

package com.xxx.common;

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

public class MultipleDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return  DbContextHolder.getDataSource();
    }
}

6.配置dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">


    <context:property-placeholder location="classpath:properties/*.properties"/>

    <bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource"
          destroy-method="close">
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="maxActive" value="10"/>
        <property name="minIdle" value="5"/>
    </bean>
    <bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource"
          destroy-method="close">
        <property name="url" value="${jdbc.url2}"/>
        <property name="username" value="${jdbc.username2}"/>
        <property name="password" value="${jdbc.password2}"/>
        <property name="driverClassName" value="${jdbc.driver2}"/>
        <property name="maxActive" value="10"/>
        <property name="minIdle" value="5"/>
    </bean>
   <bean id="dataSource" class="com.xxx.xxx.MultipleDataSource">
        <!-- 默认数据库 -->
        <property name="defaultTargetDataSource" ref="dataSource1"></property>
        <property name="targetDataSources">
            <map>
                <entry key="dataSource1" value-ref="dataSource1"></entry>
                <entry key="dataSource2" value-ref="dataSource2"></entry>
            </map>
        </property>
    </bean> 
    <!-- 切面 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <bean id="dataSourceAspect" class="com.lyorcw.common.DataSourceAspect"></bean>
    <aop:config>
        <aop:aspect ref="dataSourceAspect">
            <!-- 拦截所有service方法,在dao层添加注解 -->
            <aop:pointcut expression="execution(* com.lyorcw.resumesystem.mapper..*.*(..))" id="dataSourcePointcut"/>
            <aop:before method="intercept" pointcut-ref="dataSourcePointcut"/>
        </aop:aspect>
    </aop:config>

    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"></property>
        <property name="mapperLocations" value="classpath:/mapper/*.xml"/>
    </bean>

    <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.lyorcw.resumesystem.mapper"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="properties">
            <value>
                mappers=tk.mybatis.mapper.common.Mapper
            </value>
        </property>
    </bean>
</beans>

7.只需要在dao层加上注解就行了

package com.xxx.xxx.mapper;

import com.xxx.xxx.DataSource;
import com.xxx.xxx.user.AppResume;
import org.apache.ibatis.annotations.Param;
import tk.mybatis.mapper.common.Mapper;

import java.util.List;

public interface AppResumeMapper extends Mapper<AppResume>{
    @DataSource(value = "dataSource2")
	AppResume lookResume(AppResume appResume);
}

注解可以加在类上,也可以加在方法上面,方法级别覆盖类级别

8.总结:

步骤:
1.两个数据库分别配置不同id的DataSource
2.配置切换数据库的自定义类的路径,选中默认数据库。
3.配置aop拦截dao层的所有访问接口,在dao层注解更改数据库。

不是原创,记录下来是为了以后用到了方法查看
转载自:https://blog.csdn.net/qq_36746327/article/details/81033404

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值