本篇主要介紹Mule表達式語言,Mule Expression Language,簡稱MEL。MEL是一種輕量級,在Mule ESB使用的表達式語言,可用於訪問和計算Mule Message的Payload,Property和Variable。幾乎每一個Mule組件都可以使用MEL表達式。MEL表達式能夠幫助開發者高效和優雅地過濾,路由,處理Mule message。關於Mule message基本概念,請參考第二篇和第三篇文章。
Mule ESB是一個使用Java語言,基於Spring框架編寫的開源企業服務總線,其相關源代碼托管在GitHub上。企業服務總線英文Enterprise Service Bus,簡稱ESB。
MuleESB在眾多開源的ESB中處於領先者的地位,擁有來自世界各地數十萬個開發人員,超過數百萬的下載量。MuleSoft公司也作為開源軟件中的獨角獸,2017年在紐交所成功上市。我們作為MuleSoft的重要合作伙伴也參與其中,在六年多的時間里,使用Mule ESB企業版開發,或者Mule ESB社區版開發,構建了眾多Mule ESB實施案例,幫助國內眾多的企業成功上線企業集成項目。
我們使用Mule ESB開發的過程中,體會到它優秀的架構設計和高效的開發速度。同時也深感Mule ESB開發書籍,Mule ESB中文文檔資料非常稀少,所以使用8篇文章來寫基礎Mule ESB開發教程,講解如何使用Mule ESB開發。
- EnjoyingSoft之Mule ESB開發教程第一篇:初識Mule ESB
- EnjoyingSoft之Mule ESB開發教程第二篇:Mule ESB基本概念
- EnjoyingSoft之Mule ESB開發教程第三篇:Mule message structure - Mule message結構
- EnjoyingSoft之Mule ESB開發教程第四篇:Mule Expression Language - MEL表達式
- EnjoyingSoft之Mule ESB開發教程第五篇:控制消息的流向-數據路由
- EnjoyingSoft之Mule ESB開發教程第六篇:Data Transform - 數據轉換
- EnjoyingSoft之Mule ESB開發教程第七篇:SOAP Web Service的消費和創建
- EnjoyingSoft之Mule ESB開發教程第八篇:使用API構建Rest Service
1. MEL的優勢
在Mule ESB上有很多方法可以操作Mule Message,比如Java語言或者其他腳本語言(比如JavaScript等)。但是MEL表達式是Mule推薦使用,在Mule應用中的一個統一和標准的方法。
- MEL表達式為開發人員提供了一個一致的標准化語言,用來訪問和計算Mule Message的Payload(負載),Property(屬性)和Variable(變量)。
- MEL基於Mule特定的對象,Studio中提供auto-complete(自動完成,語法提示)的功能,幫助開發者快速編碼。
- 更重要的是,Mule的絕大多數組件都支持MEL,比如路由組件,過濾組件等。
MEL的示例,這個示例在在Mule的Logger組件中使用MEL表達式獲取FlowVars。
從下圖可以看到,我們在Logger組件中使用MEL表達式,能夠提供語法提示,該提示帶出了上一步設定的customerNo變量。
XML配置如下:
<flow name="mel-flow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<set-variable variableName="customerNo" value="#[1008]" doc:name="customerNo"/>
<logger message="The customerNo is #[flowVars.customerNo]" level="INFO" doc:name="Logger"/>
</flow>
注意:MEL是一種表達式,和腳本語言類似,但並不相同。表達式通常用於動態獲取值或者設定值,或對數據進行簡單的操作。表達式語言和腳本語言之間在功能上存在重疊,但如果您編寫的內容非常復雜,需要的不僅僅是幾行代碼,或者您需要包含條件邏輯,那么腳本語言通常會更有用。如果簡單的獲取或設定值,調用方法或執行函數,則使用表達式則更方便。
2. MEL的使用場景
MEL表達式常用的使用場景大概可以分成三種。
- 獲取值
#[payload]
- 表示獲取message的負載
#[message.inboundProperties.'http.query.params'.customerNo]
- 表示獲取查詢參數customerNo
#[payload.callMethod(parameters)
- 表示調用payload對象的callMethod方法,並獲取方法返回值
#[xpath('//root/element')]
- 表示使用xpath語法解析並獲取相應節點內容。
- 條件比較,返回的結果就是布爾變量
#[payload.amount > 2000]
#[message.inboundProperties.'http.method' == 'GET']
- 表示判斷HTTP請求是不是GET方法
- 設定值,通常用於Message Enricher組件。
#[flowVars.dbResult]
- 這里表示相應的值設定到dbResult變量中。
3. MEL的示例
-
使用表達式提取值,根據消息的內容,屬性決定執行流程。在下面的示例中,payload是一個Java對象,我們根據購買類型,將訂單分發路由到不同的JMS消息隊列中。
<choice> <when expression="#[payload.getOrderType() == 'book']"> <jms:outbound-endpoint queue="bookQueue" /> </when> <when expression="#[payload.getOrderType() == 'music']"> <jms:outbound-endpoint queue="musicQueue" /> </when> </choice>
-
使用表達式提取值,並將值傳遞給Connector,如下示例就是使用MEL計算的值設定SMTP Connector的郵件標題,郵件接收人等。
<smtp:outbound-endpoint from="#[flowVars.mailFrom]" to="#[flowVars.mailTo]" subject="#[payload.mailSubject]" doc:name="SMTP"/>
-
如果payload是Java對象,可以調用payload方法,獲取方法的返回值。示例就說調用calAmount方法,並打印計算出來的金額。
<logger message="#[payload.calAmount()]" />
4. MEL的上下文對象
我們在上述的MEL表達式示例中可以看到MEL有多個部分組成,第一部分就是上下文對象。MEL常見的上下文對象如下:
上下文對象 | 說明 |
---|---|
#[server] | 當前服務器,可以獲取服務器的時間,JDK版本等,如#[server.dateTime],#[server.javaVersion] |
#[mule] | 當前Mule實例,可以獲取Mule的版本,目錄等。如#[mule.version] |
#[app] | 當前Mule應用的實例,可以獲取應用的名稱等。如#[app.name] |
#[message] | 這個是我們最經常使用的對象,就說Mule message。如#[message.payload],#[message.inboundProperties.'http.query.params'.customerNo]等 |
server上下文對象的常用屬性:
Field | Field描述 |
---|---|
dateTime | 系統當前時間 |
host | 主機名 |
ip | 主機IP |
osName | 操作系統名稱 |
userName | 當前用戶 |
userDir | 當前用戶工作目錄 |
mule上下文對象的常用屬性:
Field | Field描述 |
---|---|
home | Mule Runtime的安裝目錄 |
version | Mule Runtime的版本 |
nodeId | 集群下的本機ID |
clusterId | 集群ID |
app上下文對象的常用屬性:
Field | Field描述 |
---|---|
name | Mule App應用名稱 |
workdir | Mule App工作目錄 |
message上下文對象的常用屬性:
Field | Field描述 |
---|---|
id | message的唯一ID |
rootId | message的根ID |
payload | message的負載 |
inboundProperties | message的inbound頭信息 |
inboundAttachments | message的inbound附件信息 |
outboundProperties | message的outbound頭信息 |
outboundAttachments | message的outbound附件信息 |
5. MEL的Variable
不同於第4點提到的上下文對象,MEL中還可以使用變量,使用變量並不要求在表達式中使用上下文對象。變量是頂層的標識符。MEL中常見的變量如下:
- flowVars - flowVars的有效范圍是在一個Flow中,定義flowVars之后,后續的Message Processor都可以使用。
- sessionVars - 在跨Flow通信時,可以使用sessionVars來傳遞變量。需要注意的是,sessionVars並不總是有效的,其實取決於Inboud Endpoint的類型。后續再出專題介紹flowVars和sessionVars等之間的區別。
#[flowVars.foo = sessionVars.bar]
上述的表達式的意思是,將session變量賦值給flow變量。
6. MEL訪問屬性
-
點語法。適用對象通常是Java Pojo。MEL中可以使用點語法來訪問相關的對象屬性,同樣對象屬性的屬性也是可以用點號來訪問的。
#[message.payload.item.name]
-
Null安全性訪問。Java編程中經常遇到NullPointerException錯誤,也就是說對空對象進行訪問操作會報錯。而在MEL表達式,可以通過點語法.?來避免出錯。如下示例,即使item為null,該表達式仍然不會報錯,它會返回null值。
#[message.payload.?item.name]
-
屬性名稱的轉義。如果屬性名稱有特殊字符,那么使用點語法會遇到問題,這個時候可以單引號進行轉義。如下示例,http.query.params是一個整體。我們訪問這個屬性名,必須使用單引號進行轉義。
#[message.inboundProperties.'http.query.params'.customerNo]
-
中括號語法。如果對象是數組,或者Map,那么可以使用中括號進行訪問
#[payload[5]]
#[payload['userName']]
7. MEL操作符
常用的操作符如下,和普通的開發語言類似。還有更多的操作符可以查閱官方手冊。
- 算術運算符 + - / * %
- 比較運算符 == != > < >= <=
- 邏輯運算符 && ||
本文同步發文於EnjoyingSoft Blogs ,CSDN,簡書
訪問EnjoyingSoft 網站,獲取更多Mule ESB 社區版 實施幫助。
歡迎轉載,但必須保留原文和此段聲明,且在文章頁面明顯位置給出原文鏈接,否則保留追究法律責任的權利。