實現思路
重寫Spring的AbstractRoutingDataSource抽象類的determineCurrentLookupKey方法。
我們來看下Spring-AbstractRoutingDataSource的源碼
AbstractRoutingDataSource獲取數據源之前會先調用determineCurrentLookupKey方法查找當前的lookupKey。
1
2
3
4
|
Object lookupKey = determineCurrentLookupKey(); DataSource dataSource = this .resolvedDataSources.get(lookupKey); ....... return dataSource; |
lookupKey為數據源標識,因此通過重寫這個查找數據源標識的方法就可以讓spring切換到指定的數據源.
從變量定義中可以知道resolvedDataSources為Map類型的對象。
private Map<Object, DataSource> resolvedDataSources;
示例
步驟一 新建Maven工程
依賴如下: pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
< 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方法獲取特定數據源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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用于持有當前線程中使用的數據源標識
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
<? 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下的全部方法 --> < 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的注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
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的線程變量中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
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配置文件中配置攔截規則
1
2
3
4
5
6
7
8
9
|
<!-- 配置數據源注解的攔截規則,比如攔截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 > |
步驟八 使用注解切換多數據源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
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" )); } }); } } |
步驟九 測試
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
<? 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
########################## ## ## ## 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 |
運行結果:
代碼
https://github.com/yangshangwei/DynamicDataSource
以上這篇Spring-基于Spring使用自定義注解及Aspect實現數據庫切換操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/yangshangwei/article/details/76223423