- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Spring-基于Spring使用自定义注解及Aspect实现数据库切换操作由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
实现思路 。
重写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下的全部方法 -->
<
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的注解 。
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 。
最后此篇关于Spring-基于Spring使用自定义注解及Aspect实现数据库切换操作的文章就讲到这里了,如果你想了解更多关于Spring-基于Spring使用自定义注解及Aspect实现数据库切换操作的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试创建一个简单的小部件,它只有一个切换按钮,但我的 AVD 模拟器上不断出现错误,提示“加载小部件有问题”。 似乎是因为我在小部件布局中添加了开关或切换按钮。 为了测试它,我创建了一个新的空
我正在使用 GLFW 进行键盘输入,但处理速度太快,因此我的 bool 开关在一次按下时被更改了 10 次,因为输入是每一帧处理的。我只需要按一次空格键即可切换状态。我当前的代码如下: if (glf
我希望完成一个相当简单的任务(我希望!) 我有两个 div 标签和一个 anchor 标签,像这样: forgot password? 我希望使用 anchor 标记在两个 div 标记之间切换,
我已经尝试了几种不同的方法,但似乎无法弄清楚如何将 span 的类从“die2”切换到“die3”以及将 div 的显示样式从“block”切换到“none”。有人有任何解决方案吗? (基本上当页面加
我正在尝试制作一个交换小部件,该小部件显示两个不同的文本。激活时,它下面显示一个TextField,顶部是不可见的,而禁用时它上面显示一个Text,而底部是不可见。但是它没有在屏幕上显示任何内容,只是
我有一个简单的 Angular 应用程序,它使用两个模板和 Controller 。放置两个按钮来切换 View 。它们调用在控件内定义的函数,该函数使用 window.location='' 来切换
我想要一个 div 切换它的类(切换)onclick,然后再次恢复到原来的类 onclick 我的代码是: function myfunc() { //the code over here
我确信这是一个常见问题,我已经尝试了该网站上的许多线程来尝试解决我的问题,但我似乎无法使其正常工作。基本上我有一个子菜单,当父菜单悬停在其上时需要显示该子菜单,但是如果您在加载完成之前将鼠标从菜单项上
我制作了一个 JavaScript 函数来隐藏单击按钮时的链接及其在该函数中的工作 function toggle() { var ele = document.getElement
我正在使用我在 JS fiddle 上找到的这个脚本:http://jsfiddle.net/Q4PUw/2/ 当我点击切换链接时,它会切换框并显示它,但是,它会跳回页面顶部,然后我必须再次向下滚动才
我正在 GoDaddy 上的共享服务器 IP 上构建 Web 应用程序。该应用程序与验证请求服务器 IP 的房地产 API 进行对话。问题是在 GoDaddy 上,我们的 IP 被列为 X,但它实际上
我在 jquery 中有一个简单的脚本,可以在 时切换 div(显示和隐藏)。被点击(我正在使用 Bootstrap )。 HTML: Advanced search This is t
我有两个 NSWindows,其中都有一个 NSPanel。我想在按下按钮时切换窗口。如何才能做到这一点?我不再需要旧窗口,所以我只想显示新窗口。 最佳答案 要聚焦第二个窗口,只需调用: [windo
我尝试在单击切换时将选项添加到选择菜单,但如果再次单击(取消选择),则可以将其删除。到目前为止,我可以在单击时向选择菜单添加单个值,但无法将其删除(切换添加切换删除) 这是我的代码: HTML
我正在尝试隐藏所属行。例如,如果您单击“子标题 1”,则将仅隐藏项目 1、项目 2 和项目 3 行。 示例: title Sub Title 1
似乎无法让它为我工作,任何人都可以为我提供帮助吗? http://codepen.io/anon/pen/kABjC 这应该根据点击打开和关闭文本部分,它采用 ID #,它只是一个数字(1,2,3,4
我正在从一个文件复制到另一个文件,并且我可以看到 Excel 在源文件和目标文件之间切换(如闪烁)。我希望宏从源复制并粘贴到目标,而不在文件之间切换(我不想闪烁)。 这里我得到了我的 Excel VB
我正在尝试制作一个带切换功能的 Accordion ,现在看起来效果很好。作为 javascript 的新手,我希望得到一些帮助,那就是它的组合方式。 http://jsfiddle.net/z3wW
我正在尝试制作一个小脚本,其中屏幕将每 100 毫秒随机更改一次背景颜色,您可以通过按一个按钮来打开和关闭它。我可以让它开始,但我不能让它停止。 这是切换的主要代码: var on = -1; fun
我确信这里应该已经涵盖了这一点,但我一直无法找到专门涉及此问题的问题。 我在一个页面中有 2 个 div,就像这样...... ...content... ...content...
我是一名优秀的程序员,十分优秀!