日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用Mule ESB与Groovy编排RESTful服务【转】很适合我们当前的架构

發布時間:2023/12/18 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Mule ESB与Groovy编排RESTful服务【转】很适合我们当前的架构 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://www.infoq.com/cn/articles/restful-services-mule?

在過去幾年中,REST風格的軟件架構獲得了越來越多的認可,這主要是因為它減少了系統對動件的需求、同時使系統耦合性更低,彈性更好。?
目前越來越多的REST資源出現在企業應用中,因此對這些資源進行編排就顯得非常重要了。比方說,典型的業務活動就包含了資源的創建,然后是資源的查找及其他資源的創建等。?

本質上來說,與RESTful服務的交互是相當簡單的:需要構造并發送適當的請求(請求頭和請求體),然后分析返回的響應(響應頭和響應體)。完成這個處 理并不需要什么特別的工具或是框架,只要有一個好用的HTTP客戶端程序庫就足夠了。除此之外,由于RESTful交互過程中所涉及到的不同實體是由所謂 的微格式定義的,因此能夠輕松解析或是輸出這些實體的能力就顯得非常重要了。?

編排與多個資源的交互是個棘手的問題。我們需要定義編排、處理錯誤并不斷嘗試,同時系統必須能夠在壓力下表現良好。作為一個集成框架,Mule提供了我們所需的一切。?

來考慮一個例子吧,某商業系統對新訂單的處理需要如下編排:?

通過向服務發送一個XML實體來創建一個新訂單。?
尋找新創建的訂單資源并從中提取出確認信息。?
根據確認信息并通過郵件網關向客戶發送一條確認消息。?
我們將在本文詳細分析上面每一步的交互過程,同時還會介紹為了獲得上述交互所需的Mule動件和Groovy特性。?

總體的編排包含了一系列通過特定路由、過濾器以及內存消息隊列(aka VM隊列)連接起來的Mule服務。 最近InfoQ上的這篇文章介紹了Mule中的消息路由,大家不妨移步一觀。?

Mule對REST的支持?
Mule提供了一種簡單而又強大的方式與RESfFul服務交互,那就是Mule RESTPack。?

Mule RESTPack提供了一整套連接器與完整的指南以幫助用戶創建新的RESTful應用。在本文撰寫之際,該軟件包提供了三種傳送器,分別基于三種流行的REST框架:Abdera、Jersey及Restlet。這樣我們就可以輕松公開新的資源,但如何集成現有的REST資源呢??

好消息是Mule標準的腳本模塊所提供的Groovy支持有助于Mule HTTP傳送器的使用,這樣我們就可以成功與RESTful服務交互了。?
向Mule發送POST請求?
首先來看看第一個交互。HTTP向特定的資源發送一個XML實體來創建訂單,如以下程序片段所示:?

POST /orders HTTP 1.1?
...?
Java代碼??
  • <order?xmlns='urn:acme:order:3:1'>??
  • ???<customerId>123456</customerId>??
  • ???<productId>P987C</productId>??
  • ???<quantity>2</quantity>??
  • </order>??

  • 如果成功服務器的響應如下:?

    201 Created?
    Location: http://acme.com/order/O13579?
    ...?
    <order id='O13579' />?
    在Mule中,我們可以通過一個簡單的HTTP輸出端點(outbound endpoint)實現該交互。注意到交互本身是通過向訂單創建服務發送一個包含請求值(客戶與產品ID、數量)的映射而觸發的。該服務如下所示:?

    Java代碼??
  • <service?name="OrderCreationService">???
  • ??<inbound>???
  • ????<inbound-endpoint?ref="OrderCreationQueue"?/>???
  • ??</inbound>???
  • ??<outbound>???
  • ????<chaining-router>???
  • ????????<http:outbound-endpoint?synchronous="true"???
  • ??????????????responseTimeout="15"?method="POST"???
  • ??????????????host="${acme.order.hostname}"???
  • ??????????????port="${acme.order.port}"?path="orders"???
  • ??????????????user="${acme.order.username}"???
  • ??????????????password="${acme.order.password}"???
  • ??????????????contentType="application/vnd.acme+xml"?encoding="UTF-8">???
  • ??????????????<transformers>???
  • ????????????????<transformer?ref="OrderMapToMicroformat"?/>???
  • ??????????????</transformers>???
  • ??????????????<response-transformers>???
  • ??????????????????<message-properties-transformer>???
  • ????????????????????????<add-message-property?key="OrderPlaced"???
  • ????????????????????????????value="#[groovy:message.getStringProperty('http.status','ERR')=='201']"?/>???
  • ????????????????????????<add-message-property???
  • ????????????????????????????key="OrderResourceLocation"???
  • ????????????????????????????value="#[groovy:message.getStringProperty('Location','')]"?/>???
  • ??????????????????</message-properties-transformer>???
  • ??????????????????<object-to-string-transformer?/>???
  • ??????????????</response-transformers>???
  • ?????????</http:outbound-endpoint>???
  • ?????????<outbound-endpoint?ref="OrderCreationResultQueue"?/>???
  • ???</chaining-router>???????
  • ??</outbound>???
  • </service>??

  • 這全是XML,我們來仔細分析一下:?

    名為OrderCreationQueue的管道(可以是VM隊列或是JMS隊列)接收消息。?
    接收到的消息被直接傳遞到另一個路由,該路由會將HTTP POST的結果發送到下一個服務,該服務通過名為OrderCreationResultQueue(異步的VM隊列)的管道對調用結果進行分析。?
    通過標準的輸出端點在Groovy轉換器上執行該HTTP POST請求:?
    請求訂單的微格式是通過一個特定的傳送器創建的,下一節將對其進行詳細介紹。?
    通過一小段腳本將結果代碼抽取出來并與期望值進行比對。進行比較的目的在于將后面的服務與純的HTTP隔離開來:我們所創建的boolean類型的屬性OrderPlaced是獨立的,其名稱與進行的編排密切相關。?
    類似的,在更具上下文含義的OrderResourceLocation名字下復制Location頭。注意,該頭 有可能丟失(在失敗的情況下),在這種情況下,我們將其值默認設為空字符串以避免將null屬性加到消息中。?
    我們使用了一個對象——字符串轉換器來“分離”HTTP響應(以流的形式返回)。多虧有了這個轉換器,流得到了完全的處理,其內容也通過使用與 HTTP交換相關的編碼轉換為字符串。當流關閉時,HTTP連接得到了釋放;我們不想一直開著它,等待后面的服務從 OrderCreationResultQueue中拿出響應消息。?
    Groovy MarkupBuilder的好處?

    OrderMapToMicroformat轉換器完成了服務中的重頭戲,而它是由Groovy的MarkupBuilder實現的。MarkupBuilder API提供了一種自然的方式生成兼容于特定微格式的XML實體:?

    Java代碼??
  • <scripting:transformer?name="OrderMapToMicroformat">???
  • ???<scripting:script?engine="groovy">?<![CDATA[???
  • ????????def?writer?=?new?StringWriter()???
  • ????????def?xml?=?new?groovy.xml.MarkupBuilder(writer)???
  • ????????xml.order(xmlns:?'urn:acme:order:3:1')?{???
  • ??????????customerId(payload.clientId)???
  • ??????????productId(payload.productCode)???
  • ??????????quantity(payload.quantity)???
  • ????????}???
  • ????????result?=?writer.toString()?]]>???
  • ????</scripting:script>???
  • </scripting:transformer>??

  • 注意map payload中的值是如何用于組裝XML元素的:這里解決了一些不匹配的命名約定(比如將clientId轉換為customerId)。?

    如你所期望的那樣,該轉換器產生了如下輸入:?

    Java代碼??
  • <order?xmlns='urn:acme:order:3:1'>???
  • ???<customerId>123456</customerId>???
  • ???<productId>P987C</productId>???
  • ???<quantity>2</quantity>???
  • </order>???

  • 除了正確的內容類型外都是訂單的RESTful服務用于創建新資源所需的內容。?

    分析?

    現在我們來看一下負責異步分析訂單創建結果并決定是否需要進一步進行編排的服務:?

    Java代碼??
  • <service?name="OrderCreationResultProcessor">???
  • ??<inbound>???
  • ????<inbound-endpoint?ref="OrderCreationResultQueue"?/>???
  • ?????<selective-consumer-router>???
  • ????????<message-property-filter?pattern="OrderPlaced=true"?/>???
  • ?????</selective-consumer-router>???
  • ?????<logging-catch-all-strategy?/>???
  • ??</inbound>???
  • ??<outbound>???
  • ????<pass-through-router>???
  • ??????<outbound-endpoint?ref="SuccessfulOrderQueue"?/>???
  • ????</pass-through-router>???
  • ??</outbound>???
  • </service>???

  • 我們使用的選擇性消費者(selective consumer)所接收的消息中一定要包含訂單成功處理的頭信息。如果該頭信息為true,那就通過一個名為SuccessfulOrderQueue 的內存隊列將該消息路由給第三個(也是最終的)服務,該服務會處理訂單成功創建的消息。注意在這個例子中我們只是簡單地將錯誤消息以日志的方式記錄下來, 但在實際應用中需要將錯誤消息發送給專門的隊列以進行后續的分析或是及時的反饋。?

    向Mule發送GET請求?
    組成該編排的最后一個服務負責HTTP GET處理,它會獲得新創建的訂單,訂單中包含了額外的值以形成一個合法的消息供email網關使用。如下是個示例交互:?

    GET /order/O13579 HTTP 1.1?
    200 OK?
    Content-Type: application/vnd.acme+xml?
    ...?
    Java代碼??
  • <order?xmlns='urn:acme:order:3:1'>???
  • ??<customerId>123456</customerId>???
  • ??<productId>P987C</productId>???
  • ??<quantity>2</quantity>???
  • ??<customerEmail>foo@bar.baz</customerEmail>???
  • ??<estimatedShipping>2009-31-12T00:00:00Z</estimatedShipping>??
  • </order>??

  • 好消息是Mule的HTTP傳送包含了一個名為rest-servicecomponent的組件,該組件簡化了服務與REST資源的交互。幸好有了這樣一個組件,我們就無需將GET操作的結果發給隨后的服務了,相反可以在單獨的服務中完成一切。除此以外,它還支持在配置中使用表達式,這樣就能實現與動態構建的URL之間的連通了。?

    Java代碼??
  • <service?name="SuccessfulOrderProcessor">???
  • <inbound>???
  • ??<inbound-endpoint?ref="SuccessfulOrderQueue"?/>???
  • </inbound>???
  • <http:rest-service-component?httpMethod="GET"???
  • ???serviceUrl="#[header:OrderResourceLocation]"?/>???
  • <outbound>???
  • ??<pass-through-router>???
  • ????<outbound-endpoint?ref="EmailGatewayQueue">???
  • ??????<transformers>???
  • ???????<object-to-string-transformer?/>???
  • ???????<transformer?ref="OrderMicroformatToEmailMap"?/>???
  • ??????</transformers>???
  • ????</outbound-endpoint>???
  • ??</pass-through-router>???
  • </outbound>???
  • </service>??

  • 在接收到成功的訂單消息后,該服務使用REST服務組件生成一個HTTP GET請求,并將該請求發送給此前存儲在OrderResourceLocation屬性(aka heade)中的URL。注意到我們是如何通過Mule表達式框架(使用#[...]語法)在組件中注入動態URL的。?

    在將GET請求的響應發送給負責與email網關進行通信的服務前,我們對XML訂單實體進行了兩次轉換:?

    如上所述,我們“分離”了響應實體。?
    使用轉換器解析XML實體并構建一個映射以供接下來的服務使用。這一次,又利用到了Groovy的強大功能。?
    Groovy's XmlSlurper Happiness?

    Groovy的XmlSlurper是解析XML微格式的理想工具,這要歸功于其類似DSL的API。?

    如下代碼展示了OrderMicroformatToEmailMap轉換器的實現:?

    Java代碼??
  • <scripting:transformer?name="OrderMicroformatToEmailMap">???
  • ??<scripting:script?engine="groovy"><![CDATA[???
  • ????def?order?=?new?XmlSlurper().parseText(payload)??
  • ????????????????.declareNamespace(acme:?'urn:acme:order:3:1')???
  • ????result?=?[emailId:'OrderConfirmation',???
  • ????????emailAddress:order.'acme:customerEmail'.text(),???
  • ????????orderId:order.@id.text()]???
  • ???]]>???
  • ??</scripting:script>???
  • </scripting:transformer>??

  • 沒錯,就兩行Groovy代碼,我們使用了一個命名空間感知的XML解析器和一個map構建器。其好處真是讓人難以置信,不過這就是創建map(email網關服務所期望的)所需的全部內容。?

    最終的REST?
    在本文中,我們遵循著一個事先定義好的編排,新訂單資源的URL是唯一的動態元素。開發者可以利用示例中介紹的轉換器和表達式來支持更多的動態交互,如果你打算遵從HATEOAS路線,你就能獲得一切。如果事實如此,那其他的Mule路由就唾手可得了,比如可以創建冪等接收者的 路由。你也看到了Groovy的強大功能和靈巧性加上Mule的通信能力極大地簡化了與RESTful服務的交互。Mule的表達式和少量的Groovy 腳本能夠有效地動態定義Mule配置。除此之外,通過使用異步的VM隊列將編排的各個步驟鏈接起來可以在最大負荷下優雅地降級,這要歸功于Mule內在的SEDA架構。?

    借助于這些強大的工具,集成REST資源變得非常簡單了。?

    祝你好運!?

    大家可以從http://dossot.net/datastore/mule-groovy-rest.tar.gz下載完整的配置和相關的測試資源,這是一個獨立的Maven項目。?

    查看英文原文:Orchestrating RESTful Services With Mule ESB And Groovy。?
    http://www.infoq.com/articles/restful-services-mule

    轉載于:https://www.cnblogs.com/yecllsl/archive/2011/03/15/1985061.html

    總結

    以上是生活随笔為你收集整理的使用Mule ESB与Groovy编排RESTful服务【转】很适合我们当前的架构的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。