Spring Integration集成框架之Message-Channel

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.csdn.net/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

01public class JmsMessageBean implements Serializable {
02      
03    private String name = null;
04  
05    private Integer age = null;
06  
07    private Date birthday = null;
08  
09    private List<String> manbers = null;
10  
11    //...getter and setter
12  
13}

一个MessageHandler:

01public class JmsMessageCustomerHandler implements MessageHandler {
02    public JmsMessageCustomerHandler() {
03    }
04  
05    @Override
06    public void handleMessage(Message<?> message) throws MessagingException {
07        //输出.
08        Object obj = message.getPayload();
09        if(obj == null) {
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));
16        } else {
17            System.out.println(ReflectionToStringBuilder.reflectionToString(message));
18        }
19    }
20}

一个消息的中转,因为我不是把消息传递给下一个系统,我只是把它简单的输出。

01public class JmsMessageCustomerTransformer implements Transformer  {
02    public JmsMessageCustomerTransformer() {
03    }
04  
05    @Override
06    public Message<?> transform(Message<?> message) {
07        //不做任何事,原样返回
08        return message;
09    }
10}

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">
12  
13    <!-- jms 连接工厂 -->
14    <bean id="activeMQJmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
15        <property name="brokerURL">
16            <value>tcp://localhost:61616</value>
17        </property>
18    </bean>
19  
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"/>
24    </bean>
25  
26    <!-- jms Topic -->
27    <bean id="myTopic" class="org.apache.activemq.command.ActiveMQTopic"
28          autowire="constructor">
29        <constructor-arg value="jmstopic" />
30    </bean>
31  
32    <bean id="messageConverter" class="net.dintegration.jms.JmsMessageConverter" />
33  
34    <bean id="messageHander" class="net.dintegration.handler.JmsMessageCustomerHandler" />
35  
36    <bean id="messageTransformer" class="net.dintegration.transformer.JmsMessageCustomerTransformer" />
37  
38    <!-- jms 模板 -->
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" />
43    </bean>
44  
45    <integration:channel id="jmsinchannel"/>
46  
47    <integration:channel id="jmsoutchannel"  />
48  
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>
52  
53    <integration:transformer ref="messageTransformer"
54                             input-channel="jmsinchannel" output-channel="jmsoutchannel" />
55    <integration:service-activator ref="messageHander" input-channel="jmsoutchannel" />
56</beans>

测试类:

1public static void main(String[] args) {
2        ClassPathXmlApplicationContext context =
3                new ClassPathXmlApplicationContext("jmsintegration/jmsIntSubscribeContext.xml");
4        context.start();
5        System.out.println("Please type something and hit return");
6    }

我在本机开启了一个ActiveMQ,上述测试类运行了之后线程会阻塞,JDK不会退出。使之接收JMS消息。

我另写了一个测试类发送了一条消息。如:

01@Test
02    public void testSendJmsMessage() throws Exception {
03        System.out.println("=============================================");
04        JmsMessageBean bean = new JmsMessageBean();
05        bean.setAge(23);
06        bean.setBirthday(new Date());
07        bean.setManbers(Arrays.asList("123", "234", "345"));
08        bean.setName("Jms");
09        publisher.sendMessage(bean);
10    }

接收消息如下:

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"/>
02  
03    <integration:channel id="jmsoutchannel"  />
04  
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>
08  
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。

你觉得呢?

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值