第1章 路由定義構(gòu)建塊
摘要
Apache Camel支持兩種用于定義路由的領域域?qū)S谜Z言(DSL):Java DSL和Spring XML DSL哮兰。定義路由的基本構(gòu)建塊是端點和處理器霹粥,其中處理器的行為通常通過表達式或邏輯判斷進行修改穿扳。Apache Camel使您可以使用多種不同的語言來定義表達式和判斷。
1.1. 實現(xiàn)RouteBuilder類
概覽
要使用領域域特定語言(DSL),請擴展RouteBuilder
類并覆蓋其configure()
方法(在其中定義路由規(guī)則)慈鸠。
您可以RouteBuilder
根據(jù)需要定義任意多個類。每個類實例化一次灌具,并向CamelContext
對象注冊青团。通常,每個RouteBuilder
對象的生命周期都由部署路由器的容器自動管理咖楣。
RouteBuilder類
作為路由開發(fā)人員督笆,您的核心任務是實現(xiàn)一個或多個RouteBuilder
類。RouteBuilder
您可以繼承兩個替代類:
-
org.apache.camel.builder.RouteBuilder
?—這是RouteBuilder
適用于部署到任何容器類型的通用基類诱贿。它在camel-core
組件中提供娃肿。 -
org.apache.camel.spring.SpringRouteBuilder
?—該基類特別適合于Spring容器咕缎。特別是,它為以下特定于Spring的功能提供了額外的支持:在Spring注冊表中查找bean(使用beanRef()
Java DSL命令)和事務(有關(guān)詳細信息料扰,請參見事務指南)凭豪。它在camel-spring
工件中提供。
將RouteBuilder
用于啟動你的路由規(guī)則類中定義的方法(例如from()
晒杈,intercept()
和exception()
)嫂伞。
實現(xiàn)RouteBuilder
例1.1“ RouteBuilder類的實現(xiàn)”顯示了一個最小的RouteBuilder
實現(xiàn)。該configure()
方法主體包含一個路由規(guī)則; 每個規(guī)則都是一條Java語句拯钻。
范例1.1 RouteBuilder類的實現(xiàn)
import org.apache.camel.builder.RouteBuilder;
public class MyRouteBuilder extends RouteBuilder {
public void configure() {
// Define routing rules here:
from("file:src/data?noop=true").to("file:target/messages");
// More rules can be included, in you like.
// ...
}
}
規(guī)則的形式指示路由器從目錄中讀取文件并將它們發(fā)送到目錄帖努。該選項指示路由器將源文件保留(而不是刪除)目錄中。 from(*URL1*).to(*URL2*)``src/data``target/messages``?noop=true``src/data
注意
當您將
contextScan
with和Spring或Blueprint一起使用以過濾RouteBuilder
類時粪般,默認情況下拼余,Apache Camel將查找單例bean。但是亩歹,您可以打開舊的行為匙监,以包含使用new選項限定范圍的原型includeNonSingletons
。
1.2. 基本Java DSL語法
什么是DSL捆憎?
特定領域語言(DSL)是為特殊目的而設計的一種迷你語言舅柜。DSL不必在邏輯上完整,但需要足夠的表達能力來充分描述所選域中的問題躲惰。通常,DSL并沒有要求一個專門的解析器变抽,翻譯础拨,編譯或。如果DSL構(gòu)造可以清晰地映射到宿主語言API中的構(gòu)造绍载,則DSL可以搭載在現(xiàn)有的面向?qū)ο笏拗髡Z言之上诡宗。
考慮假設的DSL中的以下命令序列:
command01;
command02;
command03;
您可以將這些命令映射到Java方法調(diào)用,如下所示:
command01().command02().command03()
您甚至可以將塊映射到Java方法調(diào)用击儡。例如:
command01().startBlock().command02().command03().endBlock()
DSL語法由主機語言API的數(shù)據(jù)類型隱式定義塔沃。例如,Java方法的返回類型決定了您可以合法地調(diào)用next(相當于DSL中的next命令)的方法阳谍。
路由規(guī)則語法
Apache Camel定義了用于定義路由規(guī)則的路由DSL蛀柴。您可以使用此DSL在實現(xiàn)主體中定義規(guī)則RouteBuilder.configure()
。圖1.1“本地路由規(guī)則”概述了用于定義本地路由規(guī)則的基本語法矫夯。
圖1.1. 本地路由規(guī)則
本地規(guī)則始終以from("*EndpointURL*")
方法開頭鸽疾,該方法指定路由規(guī)則的消息源(消費者端點)。然后训貌,您可以在規(guī)則中添加任意長的處理器鏈(例如filter()
)制肮。通常冒窍,您可以使用to("*EndpointURL*")
方法來結(jié)束規(guī)則,該方法指定通過規(guī)則的消息的目標(生產(chǎn)者端點)豺鼻。但是综液,不一定總是要以to()
結(jié)束規(guī)則。有其他方法可以在規(guī)則中指定消息目標儒飒。
注意
您還可以定義一個全局路由規(guī)則谬莹,第一步是用一種特殊的處理器類型的規(guī)則(如
intercept()
,exception()
或errorHandler()
)约素。全局規(guī)則不在本指南的范圍內(nèi)届良。
消費者和生產(chǎn)者
本地規(guī)則始終通過使用from("*EndpointURL*")
方法定義消費者端點開始,通常(但并非總是)通過使用to("*EndpointURL*")
方法定義生產(chǎn)者端點結(jié)束圣猎。端點URL EndpointURL可以使用在部署時配置的任何組件士葫。例如,您可以使用文件端點file:MyMessageDirectory
送悔,Apache CXF端點cxf:MyServiceName
慢显,或Apache ActiveMQ端點activemq:queue:MyQName
。有關(guān)組件類型的完整列表欠啤,請參見《Apache Camel組件參考》荚藻。
交換
一個交換對象包括一個消息時,由元數(shù)據(jù)增強的洁段。交換在Apache Camel中至關(guān)重要应狱,因為交換是通過路由規(guī)則傳播消息的標準形式。交換的主要組成部分如下:
-
In消息-是由交換包封當前消息祠丝。隨著交換通過路由的進行疾呻,可以修改此消息。因此写半,In在一個路由的開始消息通常是not作為同一In消息到達路線的終點岸蜗。該
org.apache.camel.Message
類型提供消息的通用模型,包括以下部分:- Body.
- Headers.
- Attachments.
重要的是要意識到這是消息的通用模型叠蝇。Apache Camel支持多種協(xié)議和端點類型璃岳。因此,它是not可能以規(guī)范的消息主體或郵件頭的格式悔捶。例如铃慷,JMS消息的主體與HTTP消息或Web服務消息的主體具有完全不同的格式。因此炎功,主體和標頭被聲明為
Object
類型枚冗。然后,主體和標頭的原始內(nèi)容由創(chuàng)建交換實例的端點(即出現(xiàn)在from()
命令中的端點)確定蛇损。 -
Out消息-是答復消息或已轉(zhuǎn)換消息的臨時保留區(qū)域赁温。某些處理節(jié)點(特別是
to()
命令)可以通過將 In消息視為請求坛怪,將其發(fā)送到生產(chǎn)者端點,然后從該端點接收答復來修改當前消息股囊。然后將回復消息插入交換機中的 Out消息插槽袜匿。通常,如果當前節(jié)點已設置Out消息稚疹,則Apache Camel在將交換傳遞到路由中的下一個節(jié)點之前居灯,將交換修改如下:將舊的In消息丟棄,并將Out消息移至In消息插槽内狗。因此怪嫌,答復成為新的當前消息。有關(guān)Apache Camel如何在路由中將節(jié)點連接在一起的詳細討論柳沙,請參見第2.1節(jié)“管道處理”岩灭。
但是,在一種特殊情況下赂鲤,對Out消息的處理方式有所不同噪径。如果路由起點處的使用者終結(jié)點希望收到回復消息,則將路線末尾的Out消息視為使用者終結(jié)點的回復消息(而且数初,在這種情況下找爱,最終節(jié)點必須創(chuàng)建一Out消息或消費終端將掛起)。
-
消息交換模式(MEP)-影響交換和路由中的端點之間的交互泡孩,如下所示:
- 消費者端點 -創(chuàng)建原始交換的消費者端點設置MEP的初始值车摄。初始值指示使用者端點是否期望接收答復(例如, InOut MEP)(例如仑鸥, InOnly MEP)练般。
-
生產(chǎn)者端點 — MEP影響交換沿路由遇到的生產(chǎn)者端點(例如,當交換通過
to()
節(jié)點時)锈候。例如,如果當前的MEP是 InOnly敞贡,那么to()
節(jié)點將不會期望收到來自端點的答復泵琳。有時您需要更改當前的MEP,以自定義交換與生產(chǎn)者端點的交互誊役。有關(guān)更多詳細信息获列,請參見第1.4節(jié)“端點”。
Exchange屬性-包含當前消息元數(shù)據(jù)的命名屬性列表蛔垢。
消息交換模式
使用Exchange
對象可以輕松地將消息處理概括為不同的消息交換模式击孩。例如,異步協(xié)議可能會定義一個MEP鹏漆,該MEP由一條從消費者端點流向生產(chǎn)者端點(InOnly MEP)的消息組成巩梢。另一方面创泄,RPC協(xié)議可能會定義由請求消息和回復消息(InOut MEP)組成的MEP。當前括蝠,Apache Camel支持以下MEP:
InOnly
RobustInOnly
InOut
InOptionalOut
OutOnly
RobustOutOnly
OutIn
OutOptionalIn
這些消息交換模式由枚舉類型中的常量表示org.apache.camel.ExchangePattern
鞠抑。
分組交換
有時具有封裝多個交換實例的單個交換會很有用。為此忌警,您可以使用分組交換搁拙。分組交換本質(zhì)上是一個交換實例,其中包含存儲在交換屬性中java.util.List
的Exchange
對象Exchange.GROUPED_EXCHANGE
法绵。有關(guān)如何使用分組交換的示例箕速,請參見第8.5節(jié)“聚合器”。
處理器
處理器是在可以訪問和修改通過路由交換的流的路由的節(jié)點朋譬。處理器可以采用表達式或判斷參數(shù)來修改其行為盐茎。例如,圖1.1“本地路由規(guī)則”中顯示的規(guī)則包括一個filter()
以xpath()
判斷為其參數(shù)的處理器此熬。
表達式和判斷
表達式(評估為字符串或其他數(shù)據(jù)類型)和判斷(評估為true或false)經(jīng)常作為內(nèi)置處理器類型的參數(shù)出現(xiàn)庭呜。例如,以下過濾規(guī)則僅在標頭等于value的情況下傳播in消息: foo``bar
from("seda:a").filter(header("foo").isEqualTo("bar")).to("seda:b");
如果過濾器由判斷限定犀忱,則header("foo").isEqualTo("bar")
募谎。要基于消息內(nèi)容構(gòu)造更復雜的判斷和表達式,可以使用一種表達式和判斷語言(請參閱第II部分阴汇,“路由表達式和判斷語言”)数冬。
1.3. Spring XML文件中的路由結(jié)構(gòu)
命名空間
定義XML DSL的路由模式屬于以下XML模式名稱空間:
http://camel.apache.org/schema/spring
指定結(jié)構(gòu)位置
路由模式的位置通常指定為http://camel.apache.org/schema/spring/camel-spring.xsd
,它引用Apache網(wǎng)站上模式的最新版本搀庶。例如拐纱,beans
通常按示例1.2“指定路由器模式位置”中所示配置Apache Camel Spring文件的根元素。
范例1.2 指定路由結(jié)構(gòu)位置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<!-- 在此處定義路由規(guī)則 -->
</camelContext>
</beans>
運行時結(jié)構(gòu)位置
在運行時哥倔,Apache的駱駝也不會下載從Spring 文件中指定架構(gòu)位置路由器架構(gòu)秸架。相反,Apache Camel會自動從camel-spring
JAR文件的根目錄中提取模式的副本咆蒿。這樣可以確保用于解析Spring文件的架構(gòu)版本始終與當前運行時版本匹配箫老。這很重要楚午,因為在Apache網(wǎng)站上發(fā)布的架構(gòu)的最新版本可能與您當前使用的運行時版本不匹配。
使用XML編輯器
通常,建議您使用功能全面的XML編輯器來編輯Spring文件在辆。XML編輯器的自動完成功能使編寫符合路由器架構(gòu)的XML變得更加容易晶姊,并且如果XML格式不正確猿妈,編輯器可以立即向您發(fā)出警告芬失。
XML編輯器通常確實依賴從您在xsi:schemaLocation
屬性中指定的位置下載模式。為了確保在編輯時使用正確的架構(gòu)版本附迷,通常最好選擇camel-spring.xsd
文件的特定版本惧互。例如哎媚,要編輯2.3版本的Apache Camel的Spring文件,可以如下修改bean元素:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring-2.3.0.xsd">
...
camel-spring.xsd
完成編輯后壹哺,請更改回默認值抄伍。要查看當前可以下載哪些模式版本,請瀏覽至Web頁面管宵,網(wǎng)址為http://camel.apache.org/schema/spring截珍。
1.4. 端點
概覽
Apache Camel端點是路由中消息的源和接收者。端點是一種非常通用的構(gòu)建塊:它必須滿足的唯一要求是它充當消息源(生產(chǎn)者端點)或消息接收器(消費者端點)箩朴。因此岗喉,Apache Camel支持多種不同的端點類型,從協(xié)議支持端點(例如HTTP)到簡單計時器端點(例如Quartz)炸庞,這些端點以固定的時間間隔生成虛擬消息钱床。Apache Camel的主要優(yōu)勢之一是,添加實現(xiàn)新端點類型的自定義組件相對容易埠居。
端點URI
端點由端點URI標識查牌,端點URI具有以下一般形式:
scheme:contextPath[?queryOptions]
URI 方案標識協(xié)議,例如http
滥壕,并且contextPath提供該協(xié)議解釋的URI詳細信息纸颜。此外,大多數(shù)方案都允許您定義查詢選項queryOptions绎橘,這些選項以以下格式指定:
?option01=value01&option02=value02&...
例如胁孙,以下HTTP URI可用于連接到Google搜索引擎頁面:
http://www.google.com
以下文件URI可用于讀取C:\temp\src\data
目錄下出現(xiàn)的所有文件:
file://C:/temp/src/data
并非每個方案都代表一個協(xié)議。有時称鳞,方案僅提供對有用工具的訪問涮较,例如計時器。
例如冈止,以下計時器端點URI每秒鐘(= 1000毫秒)生成一次交換狂票。您可以使用它來計劃路線中的活動。
timer:// tickTock熙暴?period = 1000
使用長端點URI
由于提供的所有隨附配置信息苫亦,有時端點URI可能變得很長。從JBoss Fuse 6.2起怨咪,您可以采用兩種方法使使用較長URI的工作更易于管理。
-
分別配置端點
您可以單獨配置端點润匙,并且可以使用路由的速記ID從路由中引用端點诗眨。
<camelContext ...> <endpoint id="foo" uri="ftp://foo@myserver"> <property name="password" value="secret"/> <property name="recursive" value="true"/> <property name="ftpClient.dataTimeout" value="30000"/> <property name="ftpClient.serverLanguageCode" value="fr"/> </endpoint> <route> <from uri="ref:foo"/> ... </route> </camelContext>
您還可以在URI中配置一些選項,然后使用該
property
屬性指定其他選項(或覆蓋URI中的選項)孕讳。<endpoint id="foo" uri="ftp://foo@myserver?recursive=true"> <property name="password" value="secret"/> <property name="ftpClient.dataTimeout" value="30000"/> <property name="ftpClient.serverLanguageCode" value="fr"/> </endpoint>
-
跨新行拆分端點配置
您可以使用新行來分割URI屬性匠楚。
<route> <from uri="ftp://foo@myserver?password=secret& recursive=true&ftpClient.dataTimeout=30000& ftpClientConfig.serverLanguageCode=fr"/> <to uri="bean:doSomething"/> </route>
注意
您可以在每行上指定一個或多個選項巍膘,每個選項之間用分隔
&
。
在URI中指定時間段
許多Apache Camel組件都有其值為時間段的選項(例如芋簿,用于指定超時值峡懈,等等)。默認情況下与斤,此類時間段選項通常指定為純數(shù)字肪康,該值解釋為毫秒時間段。但是Apache Camel還支持時間段的可讀性更高的語法撩穿,使您可以用小時磷支,分鐘和秒來表示時間段。形式上食寡,人類可讀的時間段是一個符合以下語法的字符串:
[NHour(h|hour)][NMin(m|minute)][NSec(s|second)]
方括號中的每個術(shù)語[]
都是可選的雾狈,而符號(A|B)
則表示A
和B
是替代方案。
例如抵皱,可以將timer
端點配置為45分鐘善榛,如下所示:
from("timer:foo?period=45m")
.to("log:foo");
您還可以使用小時,分鐘和秒單位的任意組合呻畸,如下所示:
from("timer:foo?period=1h15m")
.to("log:foo");
from("timer:bar?period=2h30s")
.to("log:bar");
from("timer:bar?period=3h45m58s")
.to("log:bar");
在URI選項中指定原始值
默認情況下移盆,您在URI中指定的選項值將自動進行URI編碼。在某些情況下擂错,這是不良行為味滞。例如,在設置密碼選項時钮呀,最好傳輸原始字符串而不使用 URI編碼剑鞍。
通過使用語法指定選項值可以關(guān)閉URI編碼。例如爽醋, RAW(*RawValue*)
from("SourceURI")
.to("ftp:joe@myftpserver.com?password=RAW(se+re?t&23)&binary=true")
在此示例中蚁署,密碼值作為文字值傳輸se+re?t&23
。
不區(qū)分大小寫的枚舉選項
一些端點URI選項被映射到Java enum
常量蚂四。例如光戈,level
日志組件,它可以采取的選項enum
值遂赠,INFO
久妆,WARN
,ERROR
跷睦,等筷弦。此類型轉(zhuǎn)換不區(qū)分大小寫,因此可以使用以下任何替代方法來設置日志生產(chǎn)者端點的日志記錄級別:
<to uri="log:foo?level=info"/>
<to uri="log:foo?level=INfo"/>
<to uri="log:foo?level=InFo"/>
指定URI資源
從Camel 2.17開始,基于資源的組件(例如XSLT烂琴,Velocity)可以通過ref:
用作前綴從注冊表中加載資源文件爹殊。
例如,ifmyvelocityscriptbean
并且mysimplescriptbean
是注冊表中兩個bean的ID奸绷,可以按如下方式使用這些bean的內(nèi)容:
Velocity endpoint:
------------------
from("velocity:ref:myvelocityscriptbean").<rest_of_route>.
Language endpoint (for invoking a scripting language):
-----------------------------------------------------
from("direct:start")
.to("language:simple:ref:mysimplescriptbean")
Where Camel implicitly converts the bean to a String.
Apache Camel組件
每個URI 方案都映射到一個Apache Camel組件梗夸,其中Apache Camel組件本質(zhì)上是一個端點工廠。換句話說号醉,要使用特定類型的端點反症,必須在運行時容器中部署相應的Apache Camel組件。例如扣癣,要使用JMS端點惰帽,您可以在容器中部署JMS組件。
Apache Camel提供了各種不同的組件父虑,使您能夠?qū)贸绦蚺c各種傳輸協(xié)議和第三方產(chǎn)品集成在一起该酗。例如,一些更常用的組件是:文件士嚎,JMS呜魄,CXF(Web服務),HTTP莱衩,Jetty爵嗅,Direct和Mock。有關(guān)受支持組件的完整列表笨蚁,請參閱Apache Camel組件文檔睹晒。
大多數(shù)Apache Camel組件都單獨包裝到Camel核心中。如果使用Maven構(gòu)建應用程序括细,則只需在相關(guān)組件工件上添加依賴項伪很,就可以輕松地向應用程序中添加組件(及其第三方依賴項)。例如奋单,要包括HTTP組件锉试,您可以將以下Maven依賴項添加到項目POM文件中:
<!-- Maven POM File -->
<properties>
<camel-version>{camelFullVersion}</camel-version>
...
</properties>
<dependencies>
...
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-http</artifactId>
<version>${camel-version}</version>
</dependency>
...
</dependencies>
以下組件內(nèi)置在Camel核心中(在camel-core
工件中),因此它們始終可用:
- Bean
- Browse
- Dataset
- Direct
- File
- Log
- Mock
- Properties
- Ref
- SEDA
- Timer
- VM
消費者端點
消費者端點是出現(xiàn)在路由開始處的端點(即览濒,在from()
DSL命令)呆盖。換句話說,消費者端點負責啟動路由中的處理:它創(chuàng)建一個新的交換實例(通炒眩基于它已接收或獲得的某些消息)应又,并提供一個線程來處理其余的交換。
例如乏苦,以下JMS使用者端點將消息拉出payments
隊列并在路由中對其進行處理:
from("jms:queue:payments")
.process(SomeProcessor)
.to("TargetURI");
或者等效地丁频,在Spring XML中:
<camelContext id="CamelContextID"
xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="jms:queue:payments"/>
<process ref="someProcessorId"/>
<to uri="TargetURI"/>
</route>
</camelContext>
某些組件僅是消費者-即,它們只能用于定義消費者端點。例如席里,Quartz組件專門用于定義消費者端點。以下Quartz端點每秒(1000毫秒)生成一個事件:
from("quartz://secondTimer?trigger.repeatInterval=1000")
.process(SomeProcessor)
.to("TargetURI");
如果愿意拢驾,可以使用fromF()
Java DSL命令將端點URI指定為格式字符串奖磁。例如,要將用戶名和密碼替換為FTP端點的URI繁疤,可以使用Java編寫路由咖为,如下所示:
fromF("ftp:%s@fusesource.com?password=%s", username, password)
.process(SomeProcessor)
.to("TargetURI");
其中,第一次出現(xiàn)的%s
是用username
字符串的值替換稠腊,而第二次出現(xiàn)的%s
是用password
字符串的值替換躁染。此字符串格式化機制String.format()
由C printf()
函數(shù)提供,并且與C 函數(shù)提供的格式化相似架忌。有關(guān)詳細信息吞彤,請參見java.util.Formatter。
生產(chǎn)者端點
生產(chǎn)者端點是出現(xiàn)在路由端點中間或在所述尾部(例如叹放,在to()
DSL命令)饰恕。換句話說,生產(chǎn)者端點接收現(xiàn)有的交換對象井仰,并將交換的內(nèi)容發(fā)送到指定的端點埋嵌。
例如,以下JMS生產(chǎn)者端點將當前交換的內(nèi)容推送到指定的JMS隊列中:
from("SourceURI")
.process(SomeProcessor)
.to("jms:queue:orderForms");
或等效地在Spring XML中:
<camelContext id="CamelContextID" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="SourceURI"/>
<process ref="someProcessorId"/>
<to uri="jms:queue:orderForms"/>
</route>
</camelContext>
某些組件僅是生產(chǎn)者 俱恶,也就是說雹嗦,它們只能用于定義生產(chǎn)者端點。例如合是,HTTP端點專門用于定義生產(chǎn)者端點了罪。
from("SourceURI")
.process(SomeProcessor)
.to("http://www.google.com/search?hl=en&q=camel+router");
如果愿意,可以使用toF()
Java DSL命令將端點URI指定為格式字符串端仰。例如捶惜,要將自定義Google查詢替換為HTTP URI,可以使用Java編寫路由荔烧,如下所示:
from("SourceURI")
.process(SomeProcessor)
.toF("http://www.google.com/search?hl=en&q=%s", myGoogleQuery);
%s
用您的自定義查詢字符串替換 出現(xiàn)的地方myGoogleQuery
吱七。有關(guān)詳細信息,請參見java.util.Formatter鹤竭。
1.5. 處理器
概覽
為了使路由能夠執(zhí)行比簡單地將消費者端點連接到生產(chǎn)者端點更有趣的事情踊餐,您可以在路由中添加處理器。處理器是一種命令臀稚,您可以將其插入路由規(guī)則中吝岭,以對流經(jīng)該規(guī)則的消息執(zhí)行任意處理。如表1.1“ Apache Camel處理器”所示,Apache Camel提供了多種不同的處理器窜管。
表1.1散劫。Apache駱駝處理器
Java DSL | XML DSL | 描述 |
---|---|---|
aggregate() |
aggregate |
第8.5節(jié)“聚合器”:創(chuàng)建一個聚合器,它將多個傳入的交換合并到一個交換中幕帆。 |
aop() |
aop |
使用面向方面的編程(AOP)在指定的子路徑之前和之后進行工作获搏。 |
bean() , beanRef()
|
bean |
通過在Java對象(或bean)上調(diào)用方法來處理當前交換失乾。請參見第2.4節(jié)“ Bean集成”常熙。 |
choice() |
choice |
第8.1節(jié)“基于內(nèi)容的路由器”:使用when 和otherwise 子句根據(jù)交換內(nèi)容選擇特定的子路由。 |
convertBodyTo() |
convertBodyTo |
將入棧消息正文轉(zhuǎn)換為指定的類型碱茁。 |
delay() |
delay |
第8.9節(jié)“分層”:延遲交換到路由的后半部分的傳播裸卫。 |
doTry() |
doTry |
創(chuàng)建用于處理異常,使用try / catch塊doCatch 纽竣,doFinally 和end 條款墓贿。 |
end() |
N/A | 結(jié)束當前命令塊。 |
enrich() 退个,enrichRef()
|
enrich |
第10.1節(jié)“ Content Enricher”:將當前交換與從指定的生產(chǎn)者端點URI 請求的數(shù)據(jù)結(jié)合起來募壕。 |
filter() |
filter |
第8.2節(jié)“消息過濾器”:使用判斷表達式過濾傳入的交換。 |
idempotentConsumer() |
idempotentConsumer |
第11.8節(jié)“冪等的使用者”:實現(xiàn)了一種策略來禁止重復消息语盈。 |
inheritErrorHandler() |
@inheritErrorHandler |
布爾選項舱馅,可用于禁用特定路由節(jié)點上的繼承的錯誤處理程序(在Java DSL中定義為子條款,在XML DSL中定義為屬性)刀荒。 |
inOnly() |
inOnly |
將當前交換的MEP設置為InOnly(如果沒有自變量)代嗤,或者將交換作為InOnly發(fā)送到指定的端點。 |
inOut() |
inOut |
將當前交換的MEP設置為InOut(如果沒有參數(shù))缠借,或者將交換作為InOut發(fā)送到指定的端點干毅。 |
loadBalance() |
loadBalance |
第8.10節(jié)“負載均衡器”:在一組端點上實現(xiàn)負載均衡。 |
log() |
log |
將消息記錄到控制臺泼返。 |
loop() |
loop |
第8.16節(jié)“循環(huán)”:反復將每次交換重新發(fā)送到路由的后半部分硝逢。 |
markRollbackOnly() |
@markRollbackOnly |
(事務)將當前事務標記為僅回滾(不引發(fā)異常)。在XML DSL中绅喉,此選項設置為rollback 元素上的布爾屬性渠鸽。請參閱《 Apache Karaf交易指南》。 |
markRollbackOnlyLast() |
@markRollbackOnlyLast |
(事務)如果先前已將一個或多個事務與該線程關(guān)聯(lián)柴罐,然后掛起徽缚,則此命令將最新事務標記為僅回滾(不引發(fā)異常)。在XML DSL中革屠,此選項設置為rollback 元素上的布爾屬性凿试。請參閱《 Apache Karaf交易指南》排宰。 |
marshal() |
marshal |
使用指定的數(shù)據(jù)格式轉(zhuǎn)換為低級或二進制格式,以準備通過特定的傳輸協(xié)議進行發(fā)送那婉。 |
multicast() |
multicast |
第8.13節(jié)“多播”:將當前交換多播到多個目的地板甘,每個目的地都獲得自己的交換副本。 |
onCompletion() |
onCompletion |
定義一個子路由(end() 在Java DSL中以終止)详炬,該子路由在主路由完成后執(zhí)行虾啦。另請參見第2.14節(jié)“ OnCompletion”。 |
onException() |
onException |
定義一個子路由(end() 在Java DSL中由終止)痕寓,該子路由在發(fā)生指定的異常時執(zhí)行。通常在自己的行上定義(不在路線中)蝇闭。 |
pipeline() |
pipeline |
第5.4節(jié)“管道和過濾器”:將交換發(fā)送到一系列端點呻率,其中一個端點的輸出成為下一個端點的輸入。另請參見第2.1節(jié)“管道處理”呻引。 |
policy() |
policy |
將策略應用于當前路由(當前僅用于事務策略-請參閱Apache Karaf事務指南)礼仗。 |
pollEnrich() ,pollEnrichRef()
|
pollEnrich |
第10.1節(jié)“ Content Enricher”:將當前交換與從指定使用者端點URI 輪詢的數(shù)據(jù)結(jié)合在一起逻悠。 |
process() 元践,processRef
|
process |
在當前交換上執(zhí)行自定義處理器。請參閱“自定義處理器”一節(jié)和第三部分“高級駱駝編程”童谒。 |
recipientList() |
recipientList |
第8.3節(jié)“收件人列表”:將交換發(fā)送到在運行時計算出的收件人列表(例如单旁,基于標題的內(nèi)容)。 |
removeHeader() |
removeHeader |
從交易所的“ 入棧消息中刪除指定的標頭饥伊。 |
removeHeaders() |
removeHeaders |
從交易所的“ 入椣蠡耄”消息中刪除與指定模式匹配的標題。該模式可以具有以下形式prefix\* ?:在這種情況下琅豆,它與以前綴開頭的每個名稱匹配—否則愉豺,它將被解釋為正則表達式。 |
removeProperty() |
removeProperty |
從交易所中刪除指定的交易所屬性茫因。 |
removeProperties() |
removeProperties |
從交換中刪除與指定模式匹配的屬性蚪拦。以逗號分隔的1個或多個字符串列表作為參數(shù)。第一個字符串是模式(請參見removeHeaders() 上文)冻押。后續(xù)字符串指定異常-這些屬性保留驰贷。 |
resequence() |
resequence |
第8.6節(jié)“重新排序器”:根據(jù)指定的Comparotor操作對傳入的交換重新排序。支持批處理模式和流模式翼雀。 |
rollback() |
rollback |
(事務)將當前事務標記為僅回滾(默認情況下也會引發(fā)異常)饱苟。請參閱《 Apache Karaf交易指南》。 |
routingSlip() |
routingSlip |
第8.7節(jié)“路由清單”:基于從清單頭中提取的端點URI的列表狼渊,通過動態(tài)構(gòu)建的管道路由交換箱熬。 |
sample() |
sample |
創(chuàng)建采樣調(diào)節(jié)器类垦,使您可以從路線上的流量中提取交流的樣本。 |
setBody() |
setBody |
設置交易所的“ 入棾切耄”消息的消息正文蚤认。 |
setExchangePattern() |
setExchangePattern |
將當前交換機的MEP設置為指定值。請參閱“消息交換模式”一節(jié)糕伐。 |
setHeader() |
setHeader |
設置交易所的入棧消息中的指定標頭砰琢。 |
setOutHeader() |
setOutHeader |
在交易所的出棧消息中設置指定的標頭。 |
setProperty() |
setProperty() |
設置指定的交換屬性良瞧。 |
sort() |
sort |
對In消息主體(可以選擇在其中指定自定義比較器)的內(nèi)容進行排序陪汽。 |
split() |
split |
第8.4節(jié)“拆分器”:將當前交換拆分為一系列交換,其中每個拆分交換都包含原始消息正文的一個片段褥蚯。 |
stop() |
stop |
停止路由當前交換并將其標記為已完成挚冤。 |
threads() |
threads |
創(chuàng)建線程池以同時處理路由的后半部分。 |
throttle() |
throttle |
第8.8節(jié)“節(jié)流閥”:將流量限制為指定的水平(每秒變化)赞庶。 |
throwException() |
throwException |
拋出指定的Java異常训挡。 |
to() |
to |
將交換發(fā)送到一個或多個端點。請參見第2.1節(jié)“管道處理”歧强。 |
toF() |
不適用 | 使用字符串格式將交換發(fā)送到端點澜薄。也就是說,端點URI字符串可以以C printf() 函數(shù)的樣式嵌入替換摊册。 |
transacted() |
transacted |
創(chuàng)建一個Spring事務作用域肤京,該作用域包圍路由的后半部分。請參閱《Apache Karaf交易指南》丧靡。 |
transform() |
transform |
第5.6節(jié)“消息轉(zhuǎn)換器”:將入棧消息頭復制到出棧消息頭蟆沫,并將出棧消息主體設置為指定值。 |
unmarshal() |
unmarshal |
使用指定的數(shù)據(jù)格式 將入棧消息主體從低級或二進制格式轉(zhuǎn)換為高級格式温治。 |
validate() |
validate |
采取判斷表達式以測試當前消息是否有效饭庞。如果判斷返回false ,則拋出PredicateValidationException 異常熬荆。 |
wireTap() |
wireTap |
第12.3節(jié)“電線接頭”:使用ExchangePattern.InOnly MEP 將當前交換的副本發(fā)送到指定的電線接頭URI 舟山。 |
示例
要了解如何在路由中使用處理器,請參見以下示例:
Choice
所述choice()
處理器是用于路由傳入消息到替代端點生產(chǎn)條件語句卤恳。每個替代生產(chǎn)者端點之前都有一個when()
方法累盗,該方法采用判斷參數(shù)。如果判斷為true突琳,則選擇以下目標若债,否則處理將繼續(xù)進行到when()
規(guī)則中的下一個方法。例如拆融,以下choice()
處理器根據(jù)Predicate1和Predicate2的值將傳入消息定向到Target1蠢琳,Target2或Target3:
from("SourceURL")
.choice()
.when(Predicate1).to("Target1")
.when(Predicate2).to("Target2")
.otherwise().to("Target3");
或等效地在Spring XML中:
<camelContext id="buildSimpleRouteWithChoice" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="SourceURL"/>
<choice>
<when>
<!-- First predicate -->
<simple>header.foo = 'bar'</simple>
<to uri="Target1"/>
</when>
<when>
<!-- Second predicate -->
<simple>header.foo = 'manchu'</simple>
<to uri="Target2"/>
</when>
<otherwise>
<to uri="Target3"/>
</otherwise>
</choice>
</route>
</camelContext>
在Java DSL中啊终,有一種特殊情況,您可能需要使用該endChoice()
命令傲须。一些標準的Apache Camel處理器使您可以使用特殊的子句來指定額外的參數(shù)蓝牲,從而有效地打開通常由end()
命令終止的額外級別的嵌套。例如泰讽,您可以將負載均衡器子句指定為loadBalance().roundRobin().to("mock:foo").to("mock:bar").end()
例衍,以在mock:foo
和mock:bar
端點之間負載均衡消息。但是已卸,如果負載均衡器子句嵌入在選擇條件中佛玄,則必須使用以下endChoice()
命令終止該子句:
from("direct:start")
.choice()
.when(bodyAs(String.class).contains("Camel"))
.loadBalance().roundRobin().to("mock:foo").to("mock:bar").endChoice()
.otherwise()
.to("mock:result");
Filter
所述filter()
處理器可以被用來防止到達生產(chǎn)者端點無趣消息。它只有一個判斷參數(shù):如果判斷為true累澡,則允許消息交換到達生產(chǎn)者翎嫡;如果判斷為假,則消息交換被阻止永乌。例如,以下過濾器阻止消息交換具伍,除非傳入消息包含標頭foo
翅雏,其值等于bar
:
from("SourceURL").filter(header("foo").isEqualTo("bar")).to("TargetURL");
或等效地在Spring XML中:
<camelContext id="filterRoute" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="SourceURL"/>
<filter>
<simple>header.foo = 'bar'</simple>
<to uri="TargetURL"/>
</filter>
</route>
</camelContext>
Throttle
該throttle()
處理器保證了生產(chǎn)的端點不會過載。節(jié)流器通過限制每秒可以通過的消息數(shù)來工作人芽。如果傳入消息超過指定的速率望几,則調(diào)節(jié)器將多余的消息累積在緩沖區(qū)中,然后將它們更慢地傳輸?shù)缴a(chǎn)者端點萤厅。例如橄抹,要將吞吐量速率限制為每秒100條消息,可以定義以下規(guī)則:
from("SourceURL").throttle(100).to("TargetURL");
或等效地在Spring XML中:
<camelContext id="throttleRoute" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="SourceURL"/>
<throttle maximumRequestsPerPeriod="100" timePeriodMillis="1000">
<to uri="TargetURL"/>
</throttle>
</route>
</camelContext>
自定義處理器
如果此處描述的標準處理器都不提供所需的功能惕味,則始終可以定義自己的自定義處理器楼誓。要創(chuàng)建自定義處理器,請定義一個實現(xiàn)org.apache.camel.Processor
接口并覆蓋該process()
方法的類名挥。以下定制處理器從傳入消息中MyProcessor
刪除命名的標頭foo
:
示例1.3 實施自定義處理器類
public class MyProcessor implements org.apache.camel.Processor {
public void process(org.apache.camel.Exchange exchange) {
inMessage = exchange.getIn();
if (inMessage != null) {
inMessage.removeHeader("foo");
}
}
};
要將自定義處理器插入路由器規(guī)則疟羹,請調(diào)用process()
方法,該方法提供了將處理器插入規(guī)則的通用機制禀倔。例如榄融,以下規(guī)則調(diào)用示例1.3“實現(xiàn)自定義處理器類”中定義的處理器:
org.apache.camel.Processor myProc = new MyProcessor();
from("SourceURL").process(myProc).to("TargetURL");