實現(xiàn)思路
重寫Spring的AbstractRoutingDataSource抽象類的determineCurrentLookupKey方法。
我們來看下Spring-AbstractRoutingDataSource的源碼
AbstractRoutingDataSource獲取數(shù)據(jù)源之前會先調(diào)用determineCurrentLookupKey方法查找當(dāng)前的lookupKey。
1
2
3
4
|
Object lookupKey = determineCurrentLookupKey(); DataSource dataSource = this .resolvedDataSources.get(lookupKey); ....... return dataSource; |
lookupKey為數(shù)據(jù)源標(biāo)識,因此通過重寫這個查找數(shù)據(jù)源標(biāo)識的方法就可以讓spring切換到指定的數(shù)據(jù)源.
從變量定義中可以知道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方法獲取特定數(shù)據(jù)源
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是實現(xiàn)數(shù)據(jù)源的route的核心 * .需要重寫該方法 * * @author: Mr.Yang * * @date: 2017年7月24日 下午8:28:46 */ public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceHolder.getDataSource(); } } |
步驟三 創(chuàng)建DynamicDataSourceHolder用于持有當(dāng)前線程中使用的數(shù)據(jù)源標(biāo)識
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:創(chuàng)建DynamicDataSourceHolder用于持有當(dāng)前線程中使用的數(shù)據(jù)源標(biāo)識 * * @author: Mr.Yang * * @date: 2017年7月24日 下午8:23:50 */ public class DynamicDataSourceHolder { /** * 數(shù)據(jù)源標(biāo)識保存在線程變量中,避免多線程操作數(shù)據(jù)源時互相干擾 */ private static final ThreadLocal<String> dataSourceHolder = new ThreadLocal<String>(); /** * * * @Title: setDataSource * * @Description: 設(shè)置數(shù)據(jù)源 * * @param dataSource * * @return: void */ public static void setDataSource(String dataSource) { dataSourceHolder.set(dataSource); } /** * * * @Title: getDataSource * * @Description: 獲取數(shù)據(jù)源 * * @return * * @return: String */ public static String getDataSource() { return dataSourceHolder.get(); } /** * * * @Title: clearDataSource * * @Description: 清除數(shù)據(jù)源 * * * @return: void */ public static void clearDataSource() { dataSourceHolder.remove(); } } |
步驟四 配置多個數(shù)據(jù)源和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"> <!-- 基類包,將標(biāo)注Spring注解的類自動轉(zhuǎn)化Bean,同時完成Bean的注入 --> < context:component-scan base-package = "com.artisan" /> <!-- 使用context命名空間,在xml文件中配置數(shù)據(jù)庫的properties文件 --> < context:property-placeholder location = "classpath:jdbc.properties" /> <!-- 配置數(shù)據(jù)源--> <!-- 主站點的數(shù)據(jù)源 --> < 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}" /> <!-- 備用站點的數(shù)據(jù)源 --> < 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實例數(shù)據(jù)源 --> < 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" /> <!-- 默認(rèn)數(shù)據(jù)源 --> < property name = "defaultTargetDataSource" ref = "dataSourcePR" /> </ bean > <!-- 指定lookupKey和與之對應(yīng)的數(shù)據(jù)源 --> < 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使用動態(tài)數(shù)據(jù)源的配置 --> < bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref = "dynamicDataSource" /> <!-- 配置數(shù)據(jù)源注解的攔截規(guī)則,比如攔截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 > <!-- 配置事務(wù)管理器 --> < bean id = "transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref = "dynamicDataSource" /> <!-- 通過AOP配置提供事務(wù)增強(qiáng),讓com.artisan包下所有Bean的所有方法擁有事務(wù) --> < 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 > |
配置到這里,我們就可以使用多個數(shù)據(jù)源了,只需要在操作數(shù)據(jù)庫之前只要DynamicDataSourceHolder.setDataSource(“dataSourcePR”)即可切換到數(shù)據(jù)源dataSourcePR并對數(shù)據(jù)庫dataSourcePR進(jìn)行操作了。
問題:每次使用都需要調(diào)用DynamicDataSourceHolder#setDataSource,十分繁瑣,并且難以維護(hù)。
我們可以通過Spring的AOP和注解, 直接通過注解的方式指定需要訪問的數(shù)據(jù)源。 繼續(xù)改進(jìn)下吧
步驟五 定義名為@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既可以加在方法上,也可以加在接口或者接口的實現(xiàn)類上,優(yōu)先級別:方法>實現(xiàn)類>接口。 * 如果接口、接口實現(xiàn)類以及方法上分別加了@DataSource注解來指定數(shù)據(jù)源,則優(yōu)先以方法上指定的為準(zhǔn)。 * * @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: 如果僅標(biāo)注@DataSource 默認(rèn)為PR_RB數(shù)據(jù)庫實例 * * @return * * @return: String */ String name() default DataSource.PR_RB; } |
步驟六 定義AOP切面以便攔截所有帶有注解@DataSource的方法,取出注解的值作為數(shù)據(jù)源標(biāo)識放到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的方法,取出注解的值作為數(shù)據(jù)源標(biāo)識放到DBContextHolder的線程變量中 * * @author: Mr.Yang * * @date: 2017年7月25日 上午10:51:41 */ public class DataSourceAspect { /** * * * @Title: intercept * * @Description: 攔截目標(biāo)方法,獲取由@DataSource指定的數(shù)據(jù)源標(biāo)識,設(shè)置到線程存儲中以便切換數(shù)據(jù)源 * * @param point * @throws Exception * * @return: void */ public void intercept(JoinPoint point) throws Exception { Class<?> target = point.getTarget().getClass(); MethodSignature signature = (MethodSignature) point.getSignature(); // 默認(rèn)使用目標(biāo)類型的注解,如果沒有則使用其實現(xiàn)接口的注解 for (Class<?> clazz : target.getInterfaces()) { resolveDataSource(clazz, signature.getMethod()); } resolveDataSource(target, signature.getMethod()); } /** * * * @Title: resolveDataSource * * @Description: 提取目標(biāo)對象方法注解和類型注解中的數(shù)據(jù)源標(biāo)識 * * @param clazz * @param method * * @return: void */ private void resolveDataSource(Class<?> clazz, Method method) { try { Class<?>[] types = method.getParameterTypes(); // 默認(rèn)使用類型注解 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配置文件中配置攔截規(guī)則
1
2
3
4
5
6
7
8
9
|
<!-- 配置數(shù)據(jù)源注解的攔截規(guī)則,比如攔截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 > |
步驟八 使用注解切換多數(shù)據(jù)源
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: 業(yè)務(wù)類,這里暫時作為測試多數(shù)據(jù)源切換用 * * @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實例中獲取數(shù)據(jù) service.selectDataFromPR_RB(); // 從DR的RB實例中獲取數(shù)據(jù) service.selectDataFromDR_RB(); // 從PR的CC實例中獲取數(shù)據(jù) 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()); --> <!--日志級別以及優(yōu)先級排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <!--Configuration后面的status,這個用于設(shè)置log4j2自身內(nèi)部的信息輸出,可以不設(shè)置,當(dāng)設(shè)置成trace時,你會看到log4j2內(nèi)部各種詳細(xì)輸出--> <!--monitorInterval:Log4j能夠自動檢測修改配置 文件和重新配置本身,設(shè)置間隔秒數(shù)--> < 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大小的日志會自動存入按年份-月份建立的文件夾下面并進(jìn)行壓縮,作為存檔--> < 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" /> <!-- 最多保留文件數(shù) DefaultRolloverStrategy屬性如不設(shè)置,則默認(rèn)為最多同一文件夾下7個文件,這里設(shè)置了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 |
運(yùn)行結(jié)果:
代碼
https://github.com/yangshangwei/DynamicDataSource
以上這篇Spring-基于Spring使用自定義注解及Aspect實現(xiàn)數(shù)據(jù)庫切換操作就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.csdn.net/yangshangwei/article/details/76223423