Spring-基于Spring使用自定义注解及Aspect实现数据库切换

简介: Spring-基于Spring使用自定义注解及Aspect实现数据库切换

实现思路


重写Spring的AbstractRoutingDataSource抽象类的determineCurrentLookupKey方法。

我们来看下Spring-AbstractRoutingDataSource的源码

20170728030410755.jpg

AbstractRoutingDataSource获取数据源之前会先调用determineCurrentLookupKey方法查找当前的lookupKey。

Object lookupKey = determineCurrentLookupKey();
DataSource dataSource = this.resolvedDataSources.get(lookupKey);
.......
return dataSource;


ookupKey为数据源标识,因此通过重写这个查找数据源标识的方法就可以让spring切换到指定的数据源.


从变量定义中可以知道resolvedDataSources为Map类型的对象。


private Map<Object, DataSource> resolvedDataSources; 


示例

20190201233734482.png


步骤一 新建Maven工程

依赖如下: pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.artisan</groupId>
  <artifactId>dynamicDataSource</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>dynamicDataSource</name>
  <url>http://maven.apache.org</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <file.encoding>UTF-8</file.encoding>
    <spring.version>4.3.9.RELEASE</spring.version>
    <servlet.version>3.1.0</servlet.version>
    <aspectj.version>1.8.1</aspectj.version>
    <commons-dbcp.version>1.4</commons-dbcp.version>
    <jetty.version>8.1.8.v20121106</jetty.version>
    <log4j.version>1.2.17</log4j.version>
    <log4j2.version>2.8.2</log4j2.version>
    <testng.version>6.8.7</testng.version>
    <oracle.version>11.2.0.4.0</oracle.version>
    <jstl.version>1.2</jstl.version>
  </properties>
  <dependencies>
    <!-- spring 依赖 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>${commons-dbcp.version}</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>${aspectj.version}</version>
    </dependency>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>${testng.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
      <scope>test</scope>
    </dependency>
    <!-- oracle jdbc driver -->
    <dependency>
      <groupId>com.oracle</groupId>
      <artifactId>ojdbc6</artifactId>
      <version>${oracle.version}</version>
    </dependency>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>${testng.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
      <scope>test</scope>
    </dependency>
    <!-- 
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>${log4j.version}</version>
    </dependency>
    -->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
      <version>${log4j2.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>${log4j2.version}</version>
    </dependency>
  </dependencies>
  <build>
    <!-- 使用JDK1.7编译 -->
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

步骤二 继承AbstractRoutingDataSource并重写determineCurrentLookupKey方法获取特定数据源

package com.artisan.dynamicDB;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
 * 
 * 
 * @ClassName: DynamicDataSource
 * 
 * @Description: 
 *               AbstractRoutingDataSource中的抽象方法determineCurrentLookupKey是实现数据源的route的核心
 *               .需要重写该方法
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年7月24日 下午8:28:46
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
  @Override
  protected Object determineCurrentLookupKey() {
    return DynamicDataSourceHolder.getDataSource();
  }
}


步骤二 继承AbstractRoutingDataSource并重写determineCurrentLookupKey方法获取特定数据源

package com.artisan.dynamicDB;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
 * 
 * 
 * @ClassName: DynamicDataSource
 * 
 * @Description: 
 *               AbstractRoutingDataSource中的抽象方法determineCurrentLookupKey是实现数据源的route的核心
 *               .需要重写该方法
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年7月24日 下午8:28:46
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
  @Override
  protected Object determineCurrentLookupKey() {
    return DynamicDataSourceHolder.getDataSource();
  }
}


步骤三 创建DynamicDataSourceHolder用于持有当前线程中使用的数据源标识

package com.artisan.dynamicDB;
/**
 * 
 * 
 * @ClassName: DynamicDataSourceHolder
 * 
 * @Description:创建DynamicDataSourceHolder用于持有当前线程中使用的数据源标识
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年7月24日 下午8:23:50
 */
public class DynamicDataSourceHolder {
  /**
   * 数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰
   */
  private static final ThreadLocal<String> dataSourceHolder = new ThreadLocal<String>();
  /**
   * 
   * 
   * @Title: setDataSource
   * 
   * @Description: 设置数据源
   * 
   * @param dataSource
   * 
   * @return: void
   */
  public static void setDataSource(String dataSource) {
    dataSourceHolder.set(dataSource);
  }
  /**
   * 
   * 
   * @Title: getDataSource
   * 
   * @Description: 获取数据源
   * 
   * @return
   * 
   * @return: String
   */
  public static String getDataSource() {
    return dataSourceHolder.get();
  }
  /**
   * 
   * 
   * @Title: clearDataSource
   * 
   * @Description: 清除数据源
   * 
   * 
   * @return: void
   */
  public static void clearDataSource() {
    dataSourceHolder.remove();
  }
}


步骤四 配置多个数据源和DynamicDataSource的bean

<?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:p="http://www.springframework.org/schema/p"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:aop="http://www.springframework.org/schema/aop" 
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:util="http://www.springframework.org/schema/util"
  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/tx 
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/util 
       http://www.springframework.org/schema/util/spring-util.xsd">
    <!-- 基类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 -->
    <context:component-scan base-package="com.artisan"/>
    <!-- 使用context命名空间,在xml文件中配置数据库的properties文件  -->
    <context:property-placeholder location="classpath:jdbc.properties" />
    <!-- 配置数据源-->  
    <!-- 主站点的数据源 -->
  <bean id="dataSourcePR" class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"
    p:driverClassName="${jdbc.driverClassNamePR}"
    p:url="${jdbc.urlPR}"
    p:username="${jdbc.usernamePR}"
    p:password="${jdbc.passwordPR}" />
  <!-- 备用站点的数据源 -->
  <bean id="dataSourceDR" class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"
    p:driverClassName="${jdbc.driverClassNameDR}"
    p:url="${jdbc.urlDR}"
    p:username="${jdbc.usernameDR}"
    p:password="${jdbc.passwordDR}" /> 
  <!-- 主站点cc实例数据源 -->
  <bean id="dataSourceCC" class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"
    p:driverClassName="${jdbc.driverClassNameCC}"
    p:url="${jdbc.urlCC}"
    p:username="${jdbc.usernameCC}"
    p:password="${jdbc.passwordCC}" />
  <bean id="dynamicDataSource" class="com.artisan.dynamicDB.DynamicDataSource">
    <property name="targetDataSources" ref="dynamicDatasourceMap" />
    <!-- 默认数据源 -->
    <property name="defaultTargetDataSource" ref="dataSourcePR" />
  </bean>
  <!-- 指定lookupKey和与之对应的数据源 -->
  <util:map id="dynamicDatasourceMap" key-type="java.lang.String">
    <entry key="dataSourcePR" value-ref="dataSourcePR" />
    <entry key="dataSourceDR" value-ref="dataSourceDR" />
    <entry key="dataSourceCC" value-ref="dataSourceCC" />
  </util:map>
  <!-- 配置Jdbc模板  JdbcTemplate使用动态数据源的配置  -->
  <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
    p:dataSource-ref="dynamicDataSource" />
  <!-- 配置数据源注解的拦截规则,比如拦截service层或者dao层的所有方法,这里拦截了com.artisan下的全部方法 -->  
   <bean id="dataSourceAspect" class="com.artisan.dynamicDB.DataSourceAspect" />
     <aop:config>
         <aop:aspect ref="dataSourceAspect">
             <!-- 拦截所有XXX方法 -->
             <aop:pointcut id="dataSourcePointcut" expression="execution(* com.artisan..*(..))"/>
             <aop:before pointcut-ref="dataSourcePointcut" method="intercept" />
         </aop:aspect>
     </aop:config>
  <!-- 配置事务管理器 -->
  <bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
    p:dataSource-ref="dynamicDataSource" />
  <!-- 通过AOP配置提供事务增强,让com.artisan包下所有Bean的所有方法拥有事务 -->
  <aop:config proxy-target-class="true">
    <aop:pointcut id="serviceMethod"
      expression="(execution(* com.artisan..*(..))) and (@annotation(org.springframework.transaction.annotation.Transactional))" />
    <aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />
  </aop:config>
  <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
      <tx:method name="*" />
    </tx:attributes>
  </tx:advice>
</beans>


配置到这里,我们就可以使用多个数据源了,只需要在操作数据库之前只要DynamicDataSourceHolder.setDataSource(“dataSourcePR”)即可切换到数据源dataSourcePR并对数据库dataSourcePR进行操作了。


问题:每次使用都需要调用DynamicDataSourceHolder#setDataSource,十分繁琐,并且难以维护。


我们可以通过Spring的AOP和注解, 直接通过注解的方式指定需要访问的数据源。 继续改进下吧


步骤五 定义名为@DataSource的注解

package com.artisan.dynamicDB;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 
 * 
 * @ClassName: DataSource 
 * 
 * 
 * @Description: 注解@DataSource既可以加在方法上,也可以加在接口或者接口的实现类上,优先级别:方法>实现类>接口。
 *               如果接口、接口实现类以及方法上分别加了@DataSource注解来指定数据源,则优先以方法上指定的为准。
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年7月24日 下午9:59:29
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
  // 和配置文件中 dynamicDatasourceMap中的key保持一致
  public static String PR_RB = "dataSourcePR";
  public static String DR_RB = "dataSourceDR";
  public static String PR_CC = "dataSourceCC";
  /**
   * 
   * 
   * @Title: name
   * 
   * @Description: 如果仅标注@DataSource 默认为PR_RB数据库实例
   * 
   * @return
   * 
   * @return: String
   */
  String name() default DataSource.PR_RB;
}


步骤六 定义AOP切面以便拦截所有带有注解@DataSource的方法,取出注解的值作为数据源标识放到DynamicDataSourceHolder的线程变量中

package com.artisan.dynamicDB;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
/**
 * 
 * 
 * @ClassName: DataSourceAspect
 * 
 * @Description: 
 *               定义AOP切面以便拦截所有带有注解@DataSource的方法,取出注解的值作为数据源标识放到DBContextHolder的线程变量中
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年7月25日 上午10:51:41
 */
public class DataSourceAspect {
  /**
   * 
   * 
   * @Title: intercept
   * 
   * @Description: 拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源
   * 
   * @param point
   * @throws Exception
   * 
   * @return: void
   */
  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());
  }
  /**
   * 
   * 
   * @Title: resolveDataSource
   * 
   * @Description: 提取目标对象方法注解和类型注解中的数据源标识
   * 
   * @param clazz
   * @param method
   * 
   * @return: void
   */
  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.name());
      }
      // 方法注解可以覆盖类型注解
      Method m = clazz.getMethod(method.getName(), types);
      if (m != null && m.isAnnotationPresent(DataSource.class)) {
        DataSource source = m.getAnnotation(DataSource.class);
        DynamicDataSourceHolder.setDataSource(source.name());
      }
    } catch (Exception e) {
      System.out.println(clazz + ":" + e.getMessage());
    }
  }
}


步骤七 在spring配置文件中配置拦截规则

  <!-- 配置数据源注解的拦截规则,比如拦截service层或者dao层的所有方法,这里拦截了com.artisan下的全部方法 -->  
   <bean id="dataSourceAspect" class="com.artisan.dynamicDB.DataSourceAspect" />
     <aop:config>
         <aop:aspect ref="dataSourceAspect">
             <!-- 拦截所有XXX方法 -->
             <aop:pointcut id="dataSourcePointcut" expression="execution(* com.artisan..*(..))"/>
             <aop:before pointcut-ref="dataSourcePointcut" method="intercept" />
         </aop:aspect>
     </aop:config>


步骤八 使用注解切换多数据源

ExtractDataService.java

package com.artisan.extractService;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Service;
import com.artisan.dynamicDB.DataSource;
/**
 * 
 * 
 * @ClassName: ExtractDataService
 * 
 * @Description: 业务类,这里暂时作为测试多数据源切换用
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年7月24日 下午9:07:38
 */
@Service
public class ExtractDataService {
  private static final Logger logger = LogManager
      .getLogger(ExtractDataService.class.getName());
  private JdbcTemplate jdbcTemplate;
  @Autowired
  public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
  }
  /**
   * 
   * 
   * @Title: selectDataFromPR
   * 
   * @Description:
   * 
   * 
   * @return: void
   */
  @DataSource(name = DataSource.PR_RB)
  public void selectDataFromPR_RB() {
    String sql = "select  subs_id from owe_event_charge  where event_inst_id = 10229001 ";
    jdbcTemplate.query(sql, new RowCallbackHandler() {
      @Override
      public void processRow(ResultSet rs) throws SQLException {
        logger.info(rs.getInt("subs_id"));
      }
    });
  }
  @DataSource(name = DataSource.DR_RB)
  public void selectDataFromDR_RB() {
    // 改为通过注解指定DB
    // DynamicDataSourceHolder.setDataSource(DBContextHolder.DATA_SOURCE_DR);
    String sql = " select  a.task_comments  from nm_task_type a  where a.task_name = 'ALARM_LOG_LEVEL' ";
    jdbcTemplate.query(sql, new RowCallbackHandler() {
      @Override
      public void processRow(ResultSet rs) throws SQLException {
        logger.info(rs.getString("task_comments"));
      }
    });
  }
  @DataSource(name = DataSource.PR_CC)
  public void selectDataFromPR_CC() {
    // DBContextHolder.setDataSource(DBContextHolder.DATA_SOURCE_CC);
    String sql = "select  acc_nbr  from acc_nbr  where  acc_nbr_id = 82233858 ";
    jdbcTemplate.query(sql, new RowCallbackHandler() {
      @Override
      public void processRow(ResultSet rs) throws SQLException {
        logger.info(rs.getString("acc_nbr"));
      }
    });
  }
}


步骤九 测试

package com.artisan;
import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import com.artisan.extractService.ExtractDataService;
/**
 * 
 * 
 * @ClassName: App
 * 
 * @Description: 入口类
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年7月24日 下午8:50:25
 */
public class App {
  public static void main(String[] args) {
    try {
      // 加载日志框架 log4j2
      LoggerContext context = (LoggerContext) LogManager
          .getContext(false);
      ResourceLoader loader = new PathMatchingResourcePatternResolver();
      Resource resource = loader.getResource("classpath:log4j2.xml");
      context.setConfigLocation(resource.getFile().toURI());
      // 加载spring配置信息
      ApplicationContext ctx = new ClassPathXmlApplicationContext(
          "classpath:spring-context.xml");
      // 从容器中获取Bean
      ExtractDataService service = ctx.getBean("extractDataService",
          ExtractDataService.class);
      // 从PR的RB实例中获取数据
      service.selectDataFromPR_RB();
      // 从DR的RB实例中获取数据
      service.selectDataFromDR_RB();
      // 从PR的CC实例中获取数据
      service.selectDataFromPR_CC();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}


其他代码

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- log4j2使用说明:
使用方式如下:
private static final Logger logger = LogManager.getLogger(实际类名.class.getName());
-->
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="info" monitorInterval="180">
  <!-- 文件路径和文件名称,方便后面引用 -->
    <Properties>
      <Property name="backupFilePatch">D:/workspace/workspace-sts/backupOracle/log/</Property>
        <Property name="fileName">backupOracle.log</Property>
      </Properties>
    <!--先定义所有的appender-->
    <appenders>
        <!--这个输出控制台的配置-->
        <Console name="Console" target="SYSTEM_OUT">
             <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY" />
            <!-- 输出日志的格式-->
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" />
        </Console>
        <!--这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFile" fileName="${backupFilePatch}${fileName}"
            filePattern="${backupFilePatch}$${date:yyyy-MM}/app-%d{yyyyMMddHHmmssSSS}.log.gz">
            <PatternLayout
                pattern="%d{yyyy.MM.dd 'at' HH:mm:ss.SSS z} %-5level %class{36} %L %M - %msg%xEx%n" />
            <!-- 日志文件大小 -->
            <SizeBasedTriggeringPolicy size="20MB" />
            <!-- 最多保留文件数 DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
    </appenders>
    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
       <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
     <logger name="org.springframework" level="INFO"></logger>
       <logger name="org.mybatis" level="INFO"></logger>
       <root level="trace">  
            <appender-ref ref="RollingFile"/>  
            <appender-ref ref="Console"/>  
         </root>  
    </loggers>
</configuration>


jdbc.properties

##########################
##
##
## dbcp datasource pool ,basic configuration first.
## the other parameters keep default for now , you can change them if you want 
##
##
##########################
#Database in Lapaz
jdbc.driverClassNamePR=oracle.jdbc.driver.OracleDriver
jdbc.urlPR=jdbc:oracle:thin:@172.25.243.4:1521:xx
jdbc.usernamePR=xxx
jdbc.passwordPR=xxxxxxxx
#Database in Scluz
jdbc.driverClassNameDR=oracle.jdbc.driver.OracleDriver
jdbc.urlDR=jdbc:oracle:thin:@172.25.246.1:1521:xx
jdbc.usernameDR=xxx
jdbc.passwordDR=xxxxxxx
#Database in Lapaz
jdbc.driverClassNameCC=oracle.jdbc.driver.OracleDriver
jdbc.urlCC=jdbc:oracle:thin:@172.25.243.3:1521:xx
jdbc.usernameCC=xxx
jdbc.passwordCC=xxxxxx


运行结果:


20170729030100597.jpg

代码


https://github.com/yangshangwei/DynamicDataSource


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
2月前
|
Java Spring 容器
【Java】Spring如何扫描自定义的注解?
【Java】Spring如何扫描自定义的注解?
36 0
|
3月前
|
安全 Java 数据库
后端进阶之路——万字总结Spring Security与数据库集成实践(五)
后端进阶之路——万字总结Spring Security与数据库集成实践(五)
|
4月前
|
Java Spring
Spring Cloud Alibaba - 26 Gateway-自定义谓词工厂RoutePredicateFactory
Spring Cloud Alibaba - 26 Gateway-自定义谓词工厂RoutePredicateFactory
56 0
|
4月前
|
Prometheus 监控 Cloud Native
Spring Boot如何自定义监控指标
Spring Boot如何自定义监控指标
29 0
|
4月前
|
Java 调度 Maven
Spring Task 自定义定时任务类
Spring Task 自定义定时任务类
36 0
|
5天前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
|
21天前
|
存储 关系型数据库 MySQL
【mybatis-plus】Springboot+AOP+自定义注解实现多数据源操作(数据源信息存在数据库)
【mybatis-plus】Springboot+AOP+自定义注解实现多数据源操作(数据源信息存在数据库)
|
2月前
|
前端开发 Java 数据安全/隐私保护
Spring Boot3自定义异常及全局异常捕获
Spring Boot3自定义异常及全局异常捕获
46 1
|
3月前
|
Java 测试技术 Maven
【SpringBoot】仿 spring-boot-project 自定义 starters
【SpringBoot】仿 spring-boot-project 自定义 starters
|
4月前
|
SQL Java 数据库连接
(数据库链接池)spring内容复习7月16日笔记
(数据库链接池)spring内容复习7月16日笔记
15 0