有人說白人的傲慢是浸透在骨子里的,雖然表面看不出來(lái),也許再待的時(shí)間長(zhǎng)點(diǎn)我對(duì)此能有些體會(huì),到時(shí)候再告訴大家??墒羌幢隳菢?,Q和我也是可以忍受的。窮人到哪里都是窮人,Q和我都出生在國(guó)內(nèi)貧窮落后的小城市,依靠自己的努力考上像樣的大學(xué),碩士畢業(yè)來(lái)到某直轄市,并得到當(dāng)?shù)氐膽艏?,但始終無(wú)法融入當(dāng)?shù)厝说纳睿藥啄暌矝]有學(xué)會(huì)直轄市人引以為傲的方言,一口普通話也讓我們受到過不少的區(qū)別對(duì)待。所以我喜歡那篇文章——《我花了18年的時(shí)間才能和你坐在一起喝咖啡》,其實(shí)我們花的時(shí)間何止18年?何必說人家有種族優(yōu)越感,即便在國(guó)內(nèi),對(duì)待自己的同胞,某些人又何嘗有過平等的心態(tài)?Q和我,不過是這艱難時(shí)世中的一對(duì)鳳凰男和鳳凰女,努力尋找著可以擋風(fēng)遮雨的一棵梧桐樹罷了!——《關(guān)山何止千萬(wàn)重》
天涯上一篇帖子里的文字,就扔這了。
突然就想到一個(gè)問題:現(xiàn)在騾子這個(gè)東西早就絕種了吧?現(xiàn)在的馬是比賽用的,驢也很罕見了,可能就剩點(diǎn)可可西里的野驢了,更別提騾子了,況且騾子不能生育,豈不是死一個(gè)少一個(gè)...
Scripting 演示mule對(duì)JSR-223的支持,先略過不表,error handler例子過一下,重點(diǎn)分析loanBroker例子。
一、Error Handler (演示了如何使用Spring beans作為service component以及向多個(gè)出站endpoint發(fā)布消息,使用了文件監(jiān)控inbound+郵件outbound)
示例包含兩個(gè)services: ExceptionManager異常管理器 和 BusinessErrorManager業(yè)務(wù)錯(cuò)誤管理器。BusinessErrorManager是個(gè)簡(jiǎn)單的service,它通過JMS接收業(yè)務(wù)異常消息并將消息記錄到控制臺(tái),以此模仿真實(shí)的異常處理應(yīng)用。
ExceptionManager接收異常消息并根據(jù)異常消息的類型進(jìn)行某些處理動(dòng)作。例如如果收到致命異常則會(huì)向系統(tǒng)管理員發(fā)送郵件;收到標(biāo)準(zhǔn)系統(tǒng)異常則寫入本地文件log,例子演示的不是異常處理、演示的是:
(我將email.properties配置為我的公司郵箱地址,那個(gè)smtp.port=25一般不用更改。啟動(dòng)errorhandler.bat,將test-data\out\FatalException.xml拖到test-data\in目錄下后即可看到console上有了反應(yīng),最后會(huì)打印出發(fā)送郵件的地址,但是我的郵箱并未實(shí)時(shí)收到郵件,當(dāng)停掉console時(shí)才收到郵件,似乎郵件不是即刻發(fā)送而是當(dāng)mule停止時(shí)關(guān)閉鉤子會(huì)flush一下隊(duì)列,什么原因暫時(shí)不清楚,作為異步消息框架這樣似乎是正常的,不過在沒有任何負(fù)載時(shí)應(yīng)該即刻發(fā)送)
在echo例子的源碼分析中分析到了Registry注冊(cè)器 為止了,因?yàn)榭丛创a和實(shí)踐例子最好穿插并行,只看源碼崩潰的,光做做例子也無(wú)法深入。
Registry從下到上的繼承體系:
SpringRegistry -> AbstractRegistry抽象類 -> Registry接口 -> org.mule.api.lifecycle.Initialisable+Disposable接口
我們看到頂層接口屬于生命周期包的,Registry注冊(cè)器 似乎與生命周期管理有關(guān),從上到下分析:
1) Initialisable生命周期接口聲明的方法initialise()在實(shí)現(xiàn)服務(wù)的初始化階段 被調(diào)用,你可以在該方法實(shí)現(xiàn)中加入任何初始化工作;Disposable接口的dispose()方法在實(shí)現(xiàn)服務(wù)的銷毀階段 被調(diào)用。實(shí)現(xiàn)者應(yīng)該在這個(gè)生命周期方法中加入釋放所有資源的處理(這兩個(gè)接口方法類似httpservlet的init和destroy,都是由外部容器去掉用,你只要在子類中覆寫即可)
2) Registry注冊(cè)器 接口包含大量類似spring BeanFactory的方法如:lookupObject(String key)、lookupObjects(Class type)、registerObject(String key, Object value)、unregisterObject(String key)
3) AbstractRegistry仍然是模版方法的抽象中間層,它把initialise()方法延遲到doInitialise()、dispose()延遲到doDispose()
4) SpringRegistry具有一個(gè)registry_id="org.mule.Registry.Spring",另外它完全是read-only的,不允許注冊(cè)或解除注冊(cè)也就是再修改狀態(tài)。目前看注冊(cè)器應(yīng)該是包含spring上下文的且具有唯一id的一種“倉(cāng)庫(kù)”。
參考一段:
當(dāng)你需要去存儲(chǔ)應(yīng)用程序能夠訪問到的運(yùn)行時(shí)數(shù)據(jù)的時(shí)候,你可以將數(shù)據(jù)作為Object對(duì)象存儲(chǔ)到Registry中。你可以在任何地方通過訪問MuleContext獲取Registry對(duì)象。
muleContext.getRegistry().registerObject(”foo”,”new MyFoo()”);
可以在任何地方使用下面的方法更新對(duì)象:
Foo foo = (Foo) muleContext.getRegistry().lookupObject("foo");foo.setBarVal(25);// Replace the previous objectmuleContext.getRegistry().registerObject("foo", foo);
三、Loan Broker (基于Enterprise Integration Patterns book 一 EIP書中的例子 ,mule不鳥JBI和SCA,唯遵SEDA 和EIP,有個(gè)性)
Loan Broker貸款中介(也叫l(wèi)oan agent service)是mule的主要演示例子,顧名思義,就是客戶向銀行申請(qǐng)貸款的故事。先看一下背景知識(shí):
以往的貸款請(qǐng)求流程如下圖:
1) 客戶customer 向不同的銀行bank 發(fā)起請(qǐng)求搜尋最優(yōu)利率。
2) 每家銀行都要向客戶詢問社保號(hào)碼ss、貸款數(shù)量以及期限。
3) 每家銀行都要對(duì)該客戶做信用背景調(diào)查:通常是咨詢征信所credit bureau (通過征信中介credit agency ),最后銀行才能根據(jù)這些信息發(fā)放貸款。
4) 客戶接收到所有銀行的反饋以后,從中選擇一家最好的,比如說利率最低。
增加貸款中介以后,這個(gè)處理流程可以更加自動(dòng)化、允許客戶在線獲取更多銀行的實(shí)時(shí)反饋,耗時(shí)要比一家一家詢問少得多:
1) 接收到客戶請(qǐng)求以后,loan broker貸款中介從征信所獲取該客戶的信用信息。
2) 替該客戶向貸方服務(wù)lender service 列出的所有銀行發(fā)出貸款請(qǐng)求(例子中這個(gè)服務(wù)啥也沒做只是個(gè)意思)
3) 將反饋的貸款額度信息打包發(fā)送回用戶供選擇(例子中就是選擇返回利率最低的那家銀行)
貸款請(qǐng)求流程如下圖:
這其中的角色包括
1、貸款中介服務(wù)http/rest(接收客戶的http貸款請(qǐng)求,包含社保號(hào)、貸款額、期限并負(fù)責(zé)相應(yīng)放貸信息)。
2、征信所服務(wù)EJB(由貸款中介公司管理的EJB外部服務(wù),做信用檢查的,暴露一個(gè)名為creditAgency的EJB的getCreaditProfile方法)
3、征信所網(wǎng)關(guān)(例子中的網(wǎng)關(guān)做的事情都是:在JMS消息總線和 外部應(yīng)用或服務(wù)/征信所服務(wù)應(yīng)用 之間整理請(qǐng)求)
4、貸方服務(wù)VM(根據(jù)客戶的資信評(píng)分等信息選擇請(qǐng)貸的銀行,本地pojo組件,決定請(qǐng)求哪幾家銀行)
5、貸方網(wǎng)關(guān)(在消息總線到貸方服務(wù)應(yīng)用之間整理請(qǐng)求)
6、銀行網(wǎng)關(guān)(向多家銀行分發(fā)貸款請(qǐng)求)
7、還有幾家銀行bank(soap協(xié)議的消息服務(wù)、為了簡(jiǎn)化、所有銀行暴露同樣的ws接口。當(dāng)然你也可以配置不同接口的多家銀行)。
這都算是應(yīng)用,以往的應(yīng)用之間通訊是點(diǎn)對(duì)點(diǎn),客戶自己去一家一家調(diào)用銀行服務(wù)、所有銀行都一遍一遍地調(diào)用征信所。而loanBroker就相當(dāng)于我們的ESB,加入loanBroker以后就不再是點(diǎn)對(duì)點(diǎn)而是點(diǎn)對(duì)面,ESB就是面、覆蓋了征信所、所有銀行及各個(gè)網(wǎng)關(guān)的一個(gè)門面(這么看ESB蠻像一個(gè)fasade的嘛),這個(gè)門面替應(yīng)用擺平一切,你只要說我要貸款!、其他的如你的資信評(píng)級(jí)、你都要請(qǐng)求誰(shuí)、你的請(qǐng)求還需要依賴什么都包辦,有事您只管說句話就得。
例子涉及異步的請(qǐng)求/響應(yīng)處理模型;對(duì)JMS、http/rest、vm、soap、EJB各種協(xié)議的調(diào)用;把bank暴露為ws。總線中的消息用LoanQuoteRequest 代表,本例中這是個(gè)javaBean格式,但是實(shí)際中往往是個(gè)xml格式(用了ESB,我發(fā)現(xiàn)對(duì)消息這個(gè)東東來(lái)說格式是五花八門的:javabean pojo、xml、http參數(shù)、stdio、soap甚至json...)
loan broker的示例包含ESB和ESN兩種布局的版本,含義參見Mule Topologies的5種拓?fù)洳季郑?/p>
ESB、ESN企業(yè)服務(wù)網(wǎng)、對(duì)等網(wǎng)(這不又成了點(diǎn)對(duì)點(diǎn)了么,不推薦)、C/S以hub為中心的輻射方式(可能性能有問題,不推薦)、管道方式(服務(wù)編排?)
loan broker示例還包含第三個(gè)版本BPM版本,使用了業(yè)務(wù)處理引擎去編排請(qǐng)求。背景知識(shí)基本學(xué)完鳥。先看ESB版本:
Loan Broker ESB基于當(dāng)前的Loan Broker示例 但是實(shí)現(xiàn)了一個(gè)完整的ESB架構(gòu),該例子演示了如何使用HTTP/REST、 Web Services、EJB、JMS,他是根據(jù)典型ESB實(shí)現(xiàn)來(lái)配置的。
Loan Broker ESB使用了JMS消息總線以提供在不同組件和應(yīng)用間的公共消息通道:
包含消息端點(diǎn)和組件類型的細(xì)節(jié)圖:
組件:
1、Loan Broker Service貸款中介服務(wù) :接收貸款請(qǐng)求(信息包括SS社保號(hào)碼、貸款額度、期限)并負(fù)責(zé)收集放貸反饋向客戶反饋。
2、Credit Agency Service征信所服務(wù) :外部服務(wù)提供者、它對(duì)客戶的授信進(jìn)行檢驗(yàn)以確保合理的放貸額度。
3、Credit Agency Gateway征信所網(wǎng)關(guān) :在消息總線和征信所應(yīng)用之間整理請(qǐng)求。
4、Lender Service貸方服務(wù) :基于客戶的資信評(píng)分,放貸額度和期限,由貸方服務(wù)選擇請(qǐng)求貸款的銀行。
5、Lender Gateway貸方網(wǎng)關(guān) :從消息總線到貸方應(yīng)用之間整理請(qǐng)求。
6、Banking Gateway銀行網(wǎng)關(guān) :基于貸方列表、向一家或多家銀行分發(fā)貸款請(qǐng)求。
總體流程:
LoanBroker 貸款中介服務(wù) 的ResponseRouter響應(yīng)路由接收對(duì)應(yīng)答地址 的響應(yīng),它選擇最低利率并返回客戶。
從這里改變方式,只看mule源碼是不行的,03年mule從sourceforge開始、05年遷至codehaus并發(fā)布1.0版本、07年吧出的2.0,現(xiàn)在(2010年)2.2.1源碼在6M左右,只看source只會(huì)事倍功半。改為以例子的源碼分析作為切入點(diǎn)。 這里的分析需要你已經(jīng)下載mule2.2.1,里面的例子中有l(wèi)oanbroker,結(jié)合著它的esb版配置文件(loanbroker\esb\conf\loan-broker-esb-mule-config.xml)分析。網(wǎng)上資料可能大多是mule1.0版本的,這里都是以2.2.1為準(zhǔn)。
本例中,消息總線(JMS、到現(xiàn)在鬧不清jms和vm的區(qū)別...似乎vm屬于jvm內(nèi)的輕量級(jí)隊(duì)列、jms就是jms范疇的消息隊(duì)列了)上的通用消息格式是java bean格式。一般情況下如JMS規(guī)范要求總線內(nèi)的通用消息是xml格式,但是mule允許你使用任何數(shù)據(jù)格式, 我們先來(lái)定義這個(gè)通用java bean:LoanQuoteRequest 的消息格式(org.mule.example.loanbroker.messages.LoanBrokerQuoteRequest):
public class LoanBrokerQuoteRequest implements Serializable{/*** Serial version*/private static final long serialVersionUID = 46866005259682607L;/** The customer request* The request contains Customer info and loan amount and duration */private CustomerQuoteRequest customerRequest;/** credit profile for the customer */private CreditProfile creditProfile;/** A list of lenders for this request */private Bank[] lenders;/** A loan quote from a bank */private LoanQuote loanQuote;//get/set方法......}
客戶的初始請(qǐng)求觸發(fā)整個(gè)事件處理流,客戶使用瀏覽器以htt協(xié)議請(qǐng)求mule rest服務(wù),這個(gè)服務(wù)當(dāng)然得向外暴露,暴露的方式就是配置貸款中介端點(diǎn) (CustomerRequestsREST):
<endpoint name="CustomerRequestsREST" address="jetty:rest://localhost:8888/loanbroker" />
這么短短一句話的配置含義:
1、內(nèi)嵌Jetty servlet引擎
2、mule啟動(dòng)jetty在8888端口上監(jiān)聽rest請(qǐng)求
3、把rest servlet綁定到/loanbroker上下文
來(lái)自客戶的初始rest請(qǐng)求格式為:
http://localhost:8888/loanbroker/?name=Ross+Mason&ssn=1234& loanAmount=10000&loanDuration=24
貸款中介端點(diǎn) 以http參數(shù)形式接收下來(lái),需要轉(zhuǎn)換為CustomerQuoteRequest對(duì)象,所以增加了一個(gè)自定義轉(zhuǎn)換器:
<custom-transformer name="RestRequestToCustomerRequest" class="org.mule.example.loanbroker.transformers.RestRequestToCustomerRequest" />
這個(gè)轉(zhuǎn)換器要用在貸款中介端點(diǎn) 上,在貸款中介服務(wù)的入站inbound配置上、入站端點(diǎn)endpoint引用了貸款中介端點(diǎn) (CustomerRequestsREST)、同時(shí)也引用了這個(gè)轉(zhuǎn)換器。也就是說從貸款中介端點(diǎn) 上接收的rest請(qǐng)求都直接用這個(gè)轉(zhuǎn)換器予以轉(zhuǎn)換:
<service name="LoanBroker"><!--貸款中介服務(wù)--><description>The LoanBroker service is our 'entry' service that accepts requests from the outside world</description><inbound><inbound-endpoint ref="CustomerRequestsREST" transformer-refs="RestRequestToCustomerRequest" />......
自定義轉(zhuǎn)換器的寫法比較簡(jiǎn)單請(qǐng)自行參見:org.mule.example.loanbroker.transformers.RestRequestToCustomerRequest,它把rest請(qǐng)求參數(shù)封裝為CustomerQuoteRequest - CQR,注意CQR是LoanBrokerQuoteRequest的成員,CQR僅僅包含三個(gè)最基本的rest請(qǐng)求參數(shù):
/** The customer that requested the quote */private Customer customer;//包含用戶名和社保號(hào)ss/** The requested loan Amount */private double loanAmount;//貸款金額/** the duration of the loan */private int loanDuration;//貸款期限
LoanBrokerQuoteRequest除了CQR還有別的成員參見上述LoanQuoteRequest 的消息格式。
繼續(xù)、參見上述總體流程中的第二步,貸款中介服務(wù) 只做在總線上觸發(fā)LoanQuoteRequest 這么一件事,mule來(lái)處理所有的路由、轉(zhuǎn)換以及對(duì)調(diào)用者的反饋。 貸款中介服務(wù)的配置如下:
<component class="org.mule.example.loanbroker.AsynchronousLoanBroker" />
具體代碼自行參看,總之貸款中介服務(wù) LoanBrokerService接口定義了一進(jìn)一出兩個(gè)方法,分別做消息的請(qǐng)求和反饋:
Object getLoanQuote(CustomerQuoteRequest request) throws LoanBrokerException;Object receiveQuote(LoanQuote quote);
AsynchronousLoanBroker對(duì)getLoanQuote方法的實(shí)現(xiàn)歸結(jié)為:
LoanBrokerQuoteRequest bqr = new LoanBrokerQuoteRequest();bqr.setCustomerRequest(request);
就是構(gòu)造一下LoanQuoteReques 這個(gè)通用消息javabean而已。下篇繼續(xù)loanBroker的分析。
聯(lián)系客服