http://my.oschina.net/zhzhenqin/blog/92064
上一篇基本介绍了Spring Integration,以及其工作模式。也许你会觉得它没有特色的东西,自己实现也没有多大难度。是的!自己实现确实是没多大难度,但是自己实现有要具有良好扩展性的还是不是那么容易的。
我们的系统经常要和其联系的多个系统一起协同工作。他们都操作着数据库的同一张表。如:一个系统向表写数据,另一个系统定时的扫描新加入的数据,然后把新加入的数据提取出来,做一些处理。然后更新标志或者转移。
这样的场景你遇到过吗? 反正我们是有很多的这样的场景。
我以这样的为例做个Demo。
我创建一个这样的数据库。DDL SQL如:
1
CREATE
TABLE
PUBLIC
.
PUBLIC
.ATTR_MESSAGE (
2
ATT_CODE
VARCHAR
(20)
NOT
NULL
,
3
PARENT_CODE
VARCHAR
(20),
7
MARK
VARCHAR
(1)
DEFAULT
'N'
,
如上面的表结构,我从别的数据库提取了几个列创建一个表。 MARK就是一个标志列,当新加入的数据为N, 处理后的会置成Y。
Spring Integration JDBC能给你完成几乎所有代码。如下面的Spring配置:
01
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
02
<
beans
xmlns
=
"http://www.springframework.org/schema/beans"
03
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
04
xmlns:integration
=
"http://www.springframework.org/schema/integration"
05
xmlns:hdbc
=
"http://www.springframework.org/schema/integration/jdbc"
06
xmlns:stream
=
"http://www.springframework.org/schema/integration/stream"
07
xsi:schemaLocation="http://www.springframework.org/schema/beans
08
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
09
http://www.springframework.org/schema/integration
10
http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
11
http://www.springframework.org/schema/integration/jdbc
12
http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc-2.1.xsd
13
http://www.springframework.org/schema/integration/stream
14
http://www.springframework.org/schema/integration/stream/spring-integration-stream-2.1.xsd">
16
<
bean
id
=
"propertyConfigurer"
17
class
=
"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
>
18
<
property
name
=
"locations"
>
20
<
value
>classpath:jdbc/jdbc.properties</
value
>
25
<
bean
id
=
"dataSource"
class
=
"org.springframework.jdbc.datasource.DriverManagerDataSource"
>
26
<
property
name
=
"driverClassName"
value
=
"${jdbc.driverClass}"
/>
27
<
property
name
=
"url"
value
=
"${jdbc.url}"
/>
28
<
property
name
=
"username"
value
=
"${jdbc.username}"
/>
29
<
property
name
=
"password"
value
=
"${jdbc.password}"
/>
32
<
bean
id
=
"transactionManager"
class
=
"org.springframework.jdbc.datasource.DataSourceTransactionManager"
>
33
<
property
name
=
"dataSource"
ref
=
"dataSource"
/>
36
<
bean
id
=
"jdbcMessageHandler"
class
=
"net.dintegration.handler.JdbcMessageHandler"
/>
38
<
integration:channel
id
=
"jdbcinchannel"
/>
40
<
hdbc:inbound-channel-adapter
channel
=
"jdbcinchannel"
data-source
=
"dataSource"
41
query
=
"SELECT ATT_CODE, PARENT_CODE, ATT_TEXT, SEQ, OPT_DATE, MARK FROM ATTR_MESSAGE WHERE MARK = 'N'"
42
update
=
"UPDATE ATTR_MESSAGE SET MARK = 'Y' WHERE ATT_CODE IN (:ATT_CODE)"
>
43
<
integration:poller
fixed-rate
=
"10000"
>
44
<
integration:transactional
/>
46
</
hdbc:inbound-channel-adapter
>
48
<
integration:service-activator
input-channel
=
"jdbcinchannel"
ref
=
"jdbcMessageHandler"
/>
请你注意其中的:
query="SELECT ATT_CODE, PARENT_CODE, ATT_TEXT, SEQ, OPT_DATE, MARK FROM ATTR_MESSAGE WHERE MARK = 'N'"
update="UPDATE ATTR_MESSAGE SET MARK = 'Y' WHERE ATT_CODE IN (:ATT_CODE)"
它做作用就是把表ATTR_MESSAGE中MARK=‘N’的数据过滤出来, 放到jdbcMessageHandler中处理,然后按照提取时的 ATT_CODE分别把标志位 MARK置成Y。
如上,我们只需要编写一个 jdbcMessageHandler处理我们的数据就好,其他的一切都让Spring Integration为我们做好了。
01
public
class
JdbcMessageHandler
implements
MessageHandler {
03
private
static
Log log = LogFactory.getLog(JdbcMessageHandler.
class
);
05
public
JdbcMessageHandler() {
09
public
void
handleMessage(Message<?> message)
throws
MessagingException {
10
Object obj = message.getPayload();
14
}
else
if
(obj
instanceof
String) {
16
}
else
if
(obj
instanceof
List) {
17
List bean = (List)obj;
20
log.info(ReflectionToStringBuilder.reflectionToString(message));
OK。我向建立的表中插入2条数据, 然后测试。测试类:
1
public
static
void
main(String[] args) {
2
ClassPathXmlApplicationContext context =
new
ClassPathXmlApplicationContext(
"jdbc/jdbcIntegrationContext.xml"
);
测试log如:
11-26 19:27:18 [INFO] [support.DefaultLifecycleProcessor(334)] Starting beans in phase 2147483647
11-26 19:27:19 [INFO] [handler.JdbcMessageHandler(49)] [{ATT_CODE=123456, PARENT_CODE=Root, ATT_TEXT=测试数据, SEQ=1, OPT_DATE=14:17:47, MARK=N}, {ATT_CODE=234567, PARENT_CODE=123456, ATT_TEXT=test, SEQ=2, OPT_DATE=14:20:41, MARK=N}]
很明显它读到了2条数据输出了。请注意,我在Spring中配置的integration:poller fixed-rate="10000",也就是说每10秒中扫描一次ATTR_MESSAGE表.我再次用一个SQL把刚处理过的数据置成N。如:
UPDATE attr_message
set mark = 'N'
它也再次输出了日志,如:
11-26 19:30:18 [INFO] [handler.JdbcMessageHandler(49)] [{ATT_CODE=123456, PARENT_CODE=Root, ATT_TEXT=测试数据, SEQ=1, OPT_DATE=14:17:47, MARK=N}, {ATT_CODE=234567, PARENT_CODE=123456, ATT_TEXT=test, SEQ=2, OPT_DATE=14:20:41, MARK=N}]
它又读取了MARK为N的数据。就这样几乎不写任何多余的代码就实现了我上面提到的场景。而我们需要做的,仅仅写一个MessageHandler处理我们的数据。
那么他的扩展性呢?
如果你仔细看了,你就发现
1
<
integration:channel
id
=
"jdbcinchannel"
/>
1
<
integration:service-activator
input-channel
=
"jdbcinchannel"
ref
=
"jdbcMessageHandler"
/>
这样的代码在上一篇JMS也曾出现过类似的.如:
01
<
integration:channel
id
=
"jmsinchannel"
/>
03
<
integration:channel
id
=
"jmsoutchannel"
/>
05
<
jms:inbound-channel-adapter
id
=
"jmsIn"
destination
=
"myTopic"
channel
=
"jmsinchannel"
jms-template
=
"jmsTemplate"
>
06
<
integration:poller
fixed-rate
=
"30000"
/>
07
</
jms:inbound-channel-adapter
>
09
<
integration:transformer
ref
=
"messageTransformer"
10
input-channel
=
"jmsinchannel"
output-channel
=
"jmsoutchannel"
/>
11
<
integration:service-activator
ref
=
"messageHander"
input-channel
=
"jmsoutchannel"
/>
是的,Spring Integration就是通过类似的方式把任何的数据通过管道一样的把数据导向下一个需要的地方。