zoukankan      html  css  js  c++  java
  • 阿里云Druid连接池配置多个数据源 SSM框架

    1.创建一个类,使用注解的形式,方便使用,该注解使用在Service层

    @Target({ElementType.TYPE,ElementType.METHOD})

    @Retention(RetentionPolicy.RUNTIME)

    public @interface DataSource {
    String value();
    }

    2.创建一个切面方法,用于拦截所有的Service方法的调用,分配数据源

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

    3.

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

    4.

    public class DynamicDataSourceHolder {

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

    /**
    * 配置mysql数据源
    */
    public static final String mysql="mysql";
    /**
    * 配置oracle数据源
    */
    public static final String oracle="oracle";
    /**
    * 配置sqlServer数据源
    */
    public static final String sqlServer="sqlServer";

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

    5.配置配置文件

    dbconfig.properties 把数据源信息储存到配置文件中,也可以配在spring-application中

    url:jdbc:mysql://localhost:3306/parkmanager?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
    driverClassName:com.mysql.jdbc.Driver
    username:root
    password:ok
    filters:stat
    maxActive:20
    initialSize:1
    maxWait:60000
    minIdle:10
    maxIdle:15
    timeBetweenEvictionRunsMillis:60000
    minEvictableIdleTimeMillis:300000
    validationQuery:SELECT 'x'
    testWhileIdle:true
    testOnBorrow:false
    testOnReturn:false
    maxOpenPreparedStatements:20
    removeAbandoned:true
    removeAbandonedTimeout:1800
    logAbandoned:true

    ApplicationContext-dataSource.xml 一个对数据源操作的配置文件

    <!-- 阿里 druid数据库连接池 -->
    <bean id="mysqlDataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
    <!-- 数据库基本信息配置 -->
    <property name="url" value="${url}" />
    <property name="username" value="${username}" />
    <property name="password" value="${password}" />
    <property name="driverClassName" value="${driverClassName}" />
    <property name="filters" value="${filters}" />
    <!-- 最大并发连接数 -->
    <property name="maxActive" value="${maxActive}" />
    <!-- 初始化连接数量 -->
    <property name="initialSize" value="${initialSize}" />
    <!-- 配置获取连接等待超时的时间 -->
    <property name="maxWait" value="${maxWait}" />
    <!-- 最小空闲连接数 -->
    <property name="minIdle" value="${minIdle}" />
    <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
    <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
    <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
    <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" />
    <property name="validationQuery" value="${validationQuery}" />
    <property name="testWhileIdle" value="${testWhileIdle}" />
    <property name="testOnBorrow" value="${testOnBorrow}" />
    <property name="testOnReturn" value="${testOnReturn}" />
    <property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}" />
    <!-- 打开removeAbandoned功能 -->
    <property name="removeAbandoned" value="${removeAbandoned}" />
    <!-- 1800秒,也就是30分钟 -->
    <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
    <!-- 关闭abanded连接时输出错误日志 -->
    <property name="logAbandoned" value="${logAbandoned}" />
    </bean>

    多个数据源 把上面的配置复制粘贴就好

    把所有数据源放在一个容器中方便sqlsession管理

    <bean id="dataSource" class="com.flc.util.dataSource.DynamicDataSource">
    <property name="targetDataSources">
    <map key-type="java.lang.String">
    <!-- 指定lookupKey和与之对应的数据源 -->
    <entry key="mysql" value-ref="mysqlDataSource"></entry>
    <entry key="oracle" value-ref="oracleDataSource"></entry>
    <entry key="sqlServer" value-ref="sqlServerDataSource"></entry>
    </map>
    </property>
    <!-- 这里可以指定默认的数据源 -->
    <property name="defaultTargetDataSource" ref="mysqlDataSource" />
    </bean>

    配置sqlsession管理

    <!-- sql会话模版 -->

    <!--这里使用的是sqlSessionTemplate,也可以不实用,具体情况分析-->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg ref="sqlSessionFactory" />
    </bean>
    <!-- 配置mybatis -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
    <!-- mapper扫描 -->
    <property name="mapperLocations" value="classpath:mybatis/*/*.xml"></property>
    </bean>

    配置事务管理器

    <!-- 拦截所有service层 同一走自定义的dataSourceAspect -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
    </bean>
    <tx:advice id="Myadvice" transaction-manager="txManager">
    <tx:attributes>
    <tx:method name="delete*" propagation="REQUIRED" read-only="false"
    rollback-for="java.lang.Exception"/>
    <tx:method name="insert*" propagation="REQUIRED" read-only="false"
    rollback-for="java.lang.Exception" />
    <tx:method name="update*" propagation="REQUIRED" read-only="false"
    rollback-for="java.lang.Exception" />
    <tx:method name="save*" propagation="REQUIRED" read-only="false"
    rollback-for="java.lang.Exception" />
    <!-- <tx:method name="find*" propagation="SUPPORTS" read-only="true"/> -->
    </tx:attributes>
    </tx:advice>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <bean id="dataSourceAspect" class="com.flc.util.dataSource.DataSourceAspect" ></bean>
    <aop:config>
    <aop:aspect ref="dataSourceAspect" >
    <!-- 拦截所有service方法 -->
    <!-- 再service层打注解 -->
    <aop:pointcut id="dataSourcePointcut" expression="execution(* com.flc.service..*(..))"/>
    <aop:before pointcut-ref="dataSourcePointcut" method="intercept" />
    </aop:aspect>
    </aop:config>

    使用方法

    @Service("userService")  //service调用
    @DataSource(value=DynamicDataSourceHolder.mysql) //选择mysql数据库
    public class UserService implements UserManager{

    }

  • 相关阅读:
    python DB.fetchall()--获取数据库所有记录列表
    pybot/robot命令参数说明【dos下执行命令pybot.bat --help查看】
    win7 dos命令窗口内容显示不全解决办法--将命令执行结果输出到一个文件中
    【python cookbook】【数据结构与算法】2 从任意长度的可迭代对象中分解元素
    【python cookbook】【数据结构与算法】1将序列分解为单独的变量
    wxPython_Phoenix在线安装
    Python 进阶(五)定制类
    Python 进阶(四)类的继承
    墓型价格分析表
    用碑情况统计
  • 原文地址:https://www.cnblogs.com/Sora-L/p/8949731.html
Copyright © 2011-2022 走看看