zoukankan      html  css  js  c++  java
  • spring 配置多数据源 (案例)

    *.properties配置:

    <!--数据连接配置一-->

    jdbc.type=mysql
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3066/qshop?useUnicode=true&amp;characterEncoding=UTF-8&amp;useFastDateParsing=false&amp;allowMultiQueries=true&amp;serverTimezone=GMT%2b8
    jdbc.username=xxxxx
    jdbc.password=xxxx

    <!--数据连接配置二-->

    merchant.jdbc.type=mysql
    merchant.jdbc.driver=com.mysql.jdbc.Driver
    merchant.jdbc.url=jdbc:mysql://localhost:3066/qshop_merchant?useUnicode=true&amp;characterEncoding=UTF-8&amp;useFastDateParsing=false&amp;allowMultiQueries=true&amp;serverTimezone=GMT%2b8
    merchant.jdbc.username=xxxx
    merchant.jdbc.password=xxxx

    spring-application.xml配置:

    <!-- 数据源一、数据源配置, 使用 druid 数据库连接池 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
    <property name="driverClassName" value="${jdbc.driver}"/>

    <!-- 基本属性 url、user、password -->
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>

    <!-- 配置初始化大小、最小、最大 -->
    <property name="initialSize" value="${jdbc.pool.init}"/>
    <property name="minIdle" value="${jdbc.pool.minIdle}"/>
    <property name="maxActive" value="${jdbc.pool.maxActive}"/>

    <!-- 配置获取连接等待超时的时间 -->
    <property name="maxWait" value="60000"/>

    <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
    <property name="timeBetweenEvictionRunsMillis" value="60000"/>

    <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
    <property name="minEvictableIdleTimeMillis" value="300000"/>

    <property name="validationQuery" value="${jdbc.testSql}"/>
    <property name="testWhileIdle" value="true"/>
    <property name="testOnBorrow" value="false"/>
    <property name="testOnReturn" value="false"/>

    <!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle使用)
    <property name="poolPreparedStatements" value="true" />
    <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> -->

    <!-- 配置监控统计拦截的filters -->
    <property name="filters" value="stat"/>
    </bean>


    <!-- 数据源二、商家数据源配置, 使用 druid 数据库连接池 -->
    <bean id="merchantdataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
    <property name="driverClassName" value="${merchant.jdbc.driver}"/>

    <!-- 基本属性 url、user、password -->
    <property name="url" value="${merchant.jdbc.url}"/>
    <property name="username" value="${merchant.jdbc.username}"/>
    <property name="password" value="${merchant.jdbc.password}"/>

    <!-- 配置初始化大小、最小、最大 -->
    <property name="initialSize" value="${jdbc.pool.init}"/>
    <property name="minIdle" value="${jdbc.pool.minIdle}"/>
    <property name="maxActive" value="${jdbc.pool.maxActive}"/>

    <!-- 配置获取连接等待超时的时间 -->
    <property name="maxWait" value="60000"/>

    <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
    <property name="timeBetweenEvictionRunsMillis" value="60000"/>

    <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
    <property name="minEvictableIdleTimeMillis" value="300000"/>

    <property name="validationQuery" value="${jdbc.testSql}"/>
    <property name="testWhileIdle" value="true"/>
    <property name="testOnBorrow" value="false"/>
    <property name="testOnReturn" value="false"/>

    <!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle使用)
    <property name="poolPreparedStatements" value="true" />
    <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> -->

    <!-- 配置监控统计拦截的filters -->
    <property name="filters" value="stat"/>
    </bean>

    <!--配置动态数据源-->

    <bean id="dynamicDataSource" class="com.yryz.qshop.modules.dynamiclink.DynamicDataSource"> 

    <property name="targetDataSources">
    <map key-type="java.lang.String">
    <!-- 指定lookupKey和与之对应的数据源 -->
    <entry key="dataSource" value-ref="dataSource"></entry>
    <entry key="merchantdataSource" value-ref="merchantdataSource"></entry>
    </map>
    </property>
    <!-- 这里可以指定默认的数据源 {最好不要指定,指定后有坑}-->
    <!-- <property name="defaultTargetDataSource" ref="dataSource" /> -->
    </bean>

    <bean id="dataSourceAspect" class="com.yryz.qshop.modules.dynamiclink.aspect.DataSourceAspect"/>
    <aop:config>
    <aop:aspect ref="dataSourceAspect">
    <aop:pointcut id="dataSourcePointcut" expression="execution(* com.yryz.qshop.modules.merchantremote.service.*.*(..))"/>
    <aop:before pointcut-ref="dataSourcePointcut" method="intercept" />
    </aop:aspect>
    </aop:config>

    动态数据源类:

    DynamicDataSourceHolder.java

    package com.yryz.qshop.modules.dynamiclink;

    public class DynamicDataSourceHolder {

    /**
    * 注意:数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰
    */
    private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal<String>();

    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();
    }

    }

    DynamicDataSource.java

    package com.yryz.qshop.modules.dynamiclink;

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

    public class DynamicDataSource extends AbstractRoutingDataSource{

    @Override
    protected Object determineCurrentLookupKey() {
    // 从自定义的位置获取数据源标识
    return DynamicDataSourceHolder.getDataSource();
    }

    }

    DataSource注解:

    package com.yryz.qshop.modules.dynamiclink.inter;

    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();
    }

    拦截器

    DataSourceAspect.java

    package com.yryz.qshop.modules.dynamiclink.aspect;

    import java.lang.reflect.Method;

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

    import com.yryz.qshop.modules.dynamiclink.DynamicDataSourceHolder;
    import com.yryz.qshop.modules.dynamiclink.inter.DataSource;

    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());
    }
    }

    }

  • 相关阅读:
    相对路径和绝对路径的问题"/"带不带斜杠
    El表达式获取项目名称
    struts 中的创建Action的三种方法
    maven中的profile文件的解析
    Maven中模块的聚合以及对jar包的继承
    Maven中解决依赖冲突的问题
    maven中的传递依赖和传递依赖的解除
    String类为什么是final的
    jdbc 报错解决办法
    org.hibernate.PropertyValueException: not-null property references a null or transient value:
  • 原文地址:https://www.cnblogs.com/austinspark-jessylu/p/7497602.html
Copyright © 2011-2022 走看看