http://my.oschina.net/zhzhenqin/blog/86586
Spring对Java企业开发的影响是巨大的,从2004年发布到现在,一直都是Java开发主要的框架,随处可见Spring的身影。我读的Spring源码不多,但不代表我对她理解的不深刻。大众熟知Struts,Hibernate其实我都一知半解,还是上学的时候听“大虾”们说的他们很厉害才学了一些,现在已经放下了好几年了。我喜欢Spring的风格和架构,也是我开发的利器。Spring发展到现在有很多的子项目,如:Spring Batch,Spring Data Redis,Spring Data Neo4j, Spring Data Hadoop, Spring Security等。哦,还有Spring Integration。
如你所见,Integration,集成!也是Spring集大成者。我是这么认为的。
Sping Integration的介绍见:http://blog.youkuaiyun.com/slivefox/article/details/3740541
Spring Integration本身并不做任何事,它通过更高层次的抽象把各种技术杂合到一起,组成一个无缝的系统。如果你熟悉UML,你就懂得抽象在软件工程的重要性。
说了这么多,Spring Integration适合做什么?如果你的系统处在各个系统的中间,需要JMS交互,又需要Database/Redis/MongoDB,还需要监听Tcp/UDP等,还有固定的文件转移,分析。还面对着时不时的更改需求的风险。那么,它再适合不过了。
在Spring Integration中,Message是它的基础构件和核心,所有的流程都围绕着Message运转。如:
payload是他可以携带的任何Object对象,Header是她包含的一些头信息。如发mail时就需要,from,to,cc等信息。正文是一段text或者html可以存储在payload中。Message总是由外部系统触发而产生,我们称他为消息生产者Producer。这也很像事件驱动模型。如:
每个Message交互的时候都需要channel。从一个channel进入,从另一个channel流出。同时另一个channel又是下一个系统的流入端。如:
他们都通过一个适配器,把Message导向每一个需要的地方,而不伤害结构。也就是说如果更改了一个地方,我们只需要更改一个适配器。
我通过一个jms做一个简单的示例。
一个简单的Bean
01
public
class
JmsMessageBean
implements
Serializable {
03
private
String name =
null
;
05
private
Integer age =
null
;
07
private
Date birthday =
null
;
09
private
List<String> manbers =
null
;
一个MessageHandler:
01
public
class
JmsMessageCustomerHandler
implements
MessageHandler {
02
public
JmsMessageCustomerHandler() {
06
public
void
handleMessage(Message<?> message)
throws
MessagingException {
08
Object obj = message.getPayload();
10
System.out.println(
"null"
);
11
}
else
if
(obj
instanceof
String) {
12
System.out.println(obj);
13
}
else
if
(obj
instanceof
JmsMessageBean) {
14
JmsMessageBean bean = (JmsMessageBean)obj;
15
System.out.println(ReflectionToStringBuilder.reflectionToString(bean));
17
System.out.println(ReflectionToStringBuilder.reflectionToString(message));
一个消息的中转,因为我不是把消息传递给下一个系统,我只是把它简单的输出。
01
public
class
JmsMessageCustomerTransformer
implements
Transformer {
02
public
JmsMessageCustomerTransformer() {
06
public
Message<?> transform(Message<?> message) {
Spring schema:
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:jms
=
"http://www.springframework.org/schema/integration/jms"
06
xsi:schemaLocation="http://www.springframework.org/schema/beans
07
http://www.springframework.org/schema/beans/spring-beans.xsd
08
http://www.springframework.org/schema/integration
09
http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
10
http://www.springframework.org/schema/integration/jms
11
http://www.springframework.org/schema/integration/jms/spring-integration-jms-2.1.xsd">
14
<
bean
id
=
"activeMQJmsFactory"
class
=
"org.apache.activemq.ActiveMQConnectionFactory"
>
15
<
property
name
=
"brokerURL"
>
16
<
value
>tcp://localhost:61616</
value
>
20
<
bean
id
=
"connectionFactory"
class
=
"org.springframework.jms.connection.CachingConnectionFactory"
>
21
<
property
name
=
"targetConnectionFactory"
ref
=
"activeMQJmsFactory"
/>
22
<
property
name
=
"sessionCacheSize"
value
=
"10"
/>
23
<
property
name
=
"cacheProducers"
value
=
"false"
/>
27
<
bean
id
=
"myTopic"
class
=
"org.apache.activemq.command.ActiveMQTopic"
28
autowire
=
"constructor"
>
29
<
constructor-arg
value
=
"jmstopic"
/>
32
<
bean
id
=
"messageConverter"
class
=
"net.dintegration.jms.JmsMessageConverter"
/>
34
<
bean
id
=
"messageHander"
class
=
"net.dintegration.handler.JmsMessageCustomerHandler"
/>
36
<
bean
id
=
"messageTransformer"
class
=
"net.dintegration.transformer.JmsMessageCustomerTransformer"
/>
39
<
bean
id
=
"jmsTemplate"
class
=
"org.springframework.jms.core.JmsTemplate"
>
40
<
property
name
=
"connectionFactory"
ref
=
"connectionFactory"
/>
41
<
property
name
=
"defaultDestination"
ref
=
"myTopic"
/>
42
<
property
name
=
"messageConverter"
ref
=
"messageConverter"
/>
45
<
integration:channel
id
=
"jmsinchannel"
/>
47
<
integration:channel
id
=
"jmsoutchannel"
/>
49
<
jms:inbound-channel-adapter
id
=
"jmsIn"
destination
=
"myTopic"
channel
=
"jmsinchannel"
jms-template
=
"jmsTemplate"
>
50
<
integration:poller
fixed-rate
=
"30000"
/>
51
</
jms:inbound-channel-adapter
>
53
<
integration:transformer
ref
=
"messageTransformer"
54
input-channel
=
"jmsinchannel"
output-channel
=
"jmsoutchannel"
/>
55
<
integration:service-activator
ref
=
"messageHander"
input-channel
=
"jmsoutchannel"
/>
测试类:
1
public
static
void
main(String[] args) {
2
ClassPathXmlApplicationContext context =
3
new
ClassPathXmlApplicationContext(
"jmsintegration/jmsIntSubscribeContext.xml"
);
5
System.out.println(
"Please type something and hit return"
);
我在本机开启了一个ActiveMQ,上述测试类运行了之后线程会阻塞,JDK不会退出。使之接收JMS消息。
我另写了一个测试类发送了一条消息。如:
02
public
void
testSendJmsMessage()
throws
Exception {
03
System.out.println(
"============================================="
);
04
JmsMessageBean bean =
new
JmsMessageBean();
06
bean.setBirthday(
new
Date());
07
bean.setManbers(Arrays.asList(
"123"
,
"234"
,
"345"
));
09
publisher.sendMessage(bean);
接收消息如下:
net.dintegration.jms.JmsMessageBean@49c54f01[name=Jms,age=23,birthday=Thu Nov 01 20:19:35 CST 2012,manbers=[123, 234, 345]]
有人会问:这些代码是不是太罗嗦了?自己实现一个spring-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"
/>
inbound-channel-adapter是在把一个jms的输入源绑定到 jmsinchannel上, transformer使用这个输入源转给 jmsoutchannel, jmsoutchannel又是下一个消费者的输入源。假如增加了从文件系统读取文件到jmsoutchannel呢?或者还有Tcp获得的数据到jmsoutchannel呢?因为inbound-channel-adapter可以把任何输入绑定到jmsinchannel。
你觉得呢?