這一部分我將簡單介紹書中關(guān)于Message和Channel的內(nèi)容华嘹,Channel的部分將會具體介紹一些常用的Channel
Message
上一篇說過豫领,Message作為整個流程傳輸?shù)男畔⒃拚恚瑢?shí)現(xiàn)了各個部分之間的解耦。它可以是任何形式弥奸,String/Object/XML..但是它包含了要傳輸?shù)乃袃?nèi)容蛤克。
Message由兩部分組成:[Message Header + PayLoad]
Message Header就像是信件的信封,雖然收件人不關(guān)心信封上的郵票闷祥,地址等內(nèi)容娱颊,但是這些內(nèi)容確保了信件能夠流到收件人手里。具體的來講就是流程中要用與決策或者執(zhí)行的時候要進(jìn)行參考的信息凯砍。PayLoad則是具體新建的內(nèi)容箱硕。
根據(jù)角色和實(shí)現(xiàn),Message可以分為三部分:
Document messages that contain only information
Command messages that instruct the recipient to perform various operations
Event messages that indicate notable occurrences in the system and to which the recipient may react
創(chuàng)建一個Message的流程:
Step 1: A Builder is created with Payload
Step 2: Headers are added
Step 3: A Message is created by the Builder
Message helloMessage = MessageBuilder.withPayload("Hello, world!").setHeader("custom.header", "Value").setHeaderIfAbsent("custom.header2", "Value2").build();
Channel
Channel在整個流程中起到了管道的作用悟衩,他不用在意消息的內(nèi)容剧罩,也幾乎不對消息進(jìn)行處理,他只需要知道消息從哪里來座泳,要往哪里去就可以了惠昔。但是他的作用并不止于一個二傳手幕与,他還可以實(shí)現(xiàn)很多分發(fā)的策略。
Channel都繼承自Message Channel類镇防,Message Channel又衍生了兩個子類:SubscribableChannel 和 PollableChannel啦鸣,他們的區(qū)別在于是否緩存,書中有兩句話說明了他們的職責(zé):SubscribableChannel就像它的名字一樣是訂閱式的来氧,無需緩存诫给,解釋為“I’ll let you know when I’ve got something”,所以他的方法返回boolean值饲漾。PollableChannel需要緩存并做輪詢操作蝙搔,解釋為“Do you have any messages for me”。
接下來用一個簡單的例子來介紹幾種Channel
Case:channelA -> service-activatorA -> channelB -> service-activatorB -> channelC -> adapterA
<channel id="channelA"/>
<service-activator input-channel="channelA" output-channel="channelB" ref="service-activatorA"/>
<channel id="channelB"/>
<service-activator input-channel="channelB" output-channel="channelC" ref="service-activatorB"/>
<channel id="channelC"/>
<outbound-channel-adapter channel="channelC" ref="adapterA"/>
有一個問題:這個流程是同步的考传,也就是說只有adapter做完才會有下一個message進(jìn)來吃型。那么如果adapter的效率不高,因?yàn)榫W(wǎng)絡(luò)或者什么原因僚楞,就會限制整個的處理速度勤晚。這個時候就應(yīng)該將service-activatorB和adapterA拆開,通過異步實(shí)現(xiàn)泉褐,就引入了帶Queue的channel赐写。配置如下:
<channel id="channelC"><queue /></channel>
下一個問題:如果有多個adapter都要發(fā)送這個flow的message,就是遇到類似分流的事情膜赃,該如何操作挺邀?這里要使用publish-subscribe-channel,所有配置以該channel為inbound的component都能接收到,但是他有一個缺點(diǎn)跳座,就是不能直接實(shí)現(xiàn)異步端铛,如果想實(shí)現(xiàn)異步還要通過bridge結(jié)構(gòu)來輔助實(shí)現(xiàn)。配置如下:
<publish-subscibe-channel id="channelC"/>
<bridge nput-channel="channelC" output-channel="channelD"/>
<channel id="channelD"><queue /></channel>
在下一個問題:如果信息處理的順序有規(guī)定疲眷,也就是說要按一定的優(yōu)先級來結(jié)束最后的flow禾蚕,要怎么做呢?可以使用priority-queue來控制進(jìn)來message的先后順序狂丝。配置如下:
<channel id="channelA"><priority-queue comparator="comparatorA"/></channel>
Channel collaborators
MessageDispatcher消息分發(fā)器换淆,有兩個子類,一個是UnicastingDispatcher,點(diǎn)對點(diǎn)進(jìn)行發(fā)布几颜,另一種是BroadcastingDispatcher進(jìn)行廣播式的分發(fā)倍试。MessageDispatcher中依賴了一個Handler,用來實(shí)現(xiàn)邏輯部分菠剩。而dispatch則實(shí)現(xiàn)Delivery易猫。
ChannelInterceptor是另一個和Channel相關(guān)的Component。它可以在Channel收到或者發(fā)送message之前或者之后進(jìn)行一些處理(攔截)具壮。它包括的方法有{preSend准颓,postSend,afterSendCompletion,preReceive,postReceive,afterReceiveCompletion}具體是做什么的也很明顯哈蝇。
在channel中注冊:channel.addInterceptor(someChannelInterceptor);
可以通過如下方式配置interceptor:
<channel id="channelC">
<interceptors><beans:ref bean="interceptorA"/></interceptors>
</channel>
還可以通過在interceptor中配置wire-tap來將message送到另一個Channel,用于分析message攘已,而不在住流程中分析炮赦。
<interceptors><wire-tap channel="monitoringChannel"/></interceptors>
interceptor使用MessageSelector決定是否channel能夠被發(fā)送。
Summary
這一部分主要是簡單介紹了Message是什么样勃,有哪些種類吠勘。主要介紹了一些Channel的一些應(yīng)用場景。其實(shí)這一部分內(nèi)容峡眶,其實(shí)看到配置是如何寫的更容易理解這個channel的使用剧防。最后一部分其實(shí)還有一些問題,可能之后在具體應(yīng)用里面具體分析辫樱。下一部分將會簡單介紹一些EndPoint峭拘。