01. 路由定義構(gòu)建塊

第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

注意

當您將contextScanwith和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ī)則

image.png

本地規(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.ListExchange對象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-springJAR文件的根目錄中提取模式的副本咆蒿。這樣可以確保用于解析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&amp;
               recursive=true&amp;ftpClient.dataTimeout=30000&amp;
               ftpClientConfig.serverLanguageCode=fr"/>
      <to uri="bean:doSomething"/>
    </route>
    

注意

您可以在每行上指定一個或多個選項巍膘,每個選項之間用分隔&amp;

在URI中指定時間段

許多Apache Camel組件都有其值為時間段的選項(例如芋簿,用于指定超時值峡懈,等等)。默認情況下与斤,此類時間段選項通常指定為純數(shù)字肪康,該值解釋為毫秒時間段。但是Apache Camel還支持時間段的可讀性更高的語法撩穿,使您可以用小時磷支,分鐘和秒來表示時間段。形式上食寡,人類可讀的時間段是一個符合以下語法的字符串:

[NHour(h|hour)][NMin(m|minute)][NSec(s|second)]

方括號中的每個術(shù)語[]都是可選的雾狈,而符號(A|B)則表示AB是替代方案。

例如抵皱,可以將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久妆,WARNERROR跷睦,等筷弦。此類型轉(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)容的路由器”:使用whenotherwise子句根據(jù)交換內(nèi)容選擇特定的子路由。
convertBodyTo() convertBodyTo 入棧消息正文轉(zhuǎn)換為指定的類型碱茁。
delay() delay 第8.9節(jié)“分層”:延遲交換到路由的后半部分的傳播裸卫。
doTry() doTry 創(chuàng)建用于處理異常,使用try / catch塊doCatch纽竣,doFinallyend條款墓贿。
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.InOnlyMEP 將當前交換的副本發(fā)送到指定的電線接頭URI 舟山。

示例

要了解如何在路由中使用處理器,請參見以下示例:

Choice

所述choice()處理器是用于路由傳入消息到替代端點生產(chǎn)條件語句卤恳。每個替代生產(chǎn)者端點之前都有一個when()方法累盗,該方法采用判斷參數(shù)。如果判斷為true突琳,則選擇以下目標若债,否則處理將繼續(xù)進行到when()規(guī)則中的下一個方法。例如拆融,以下choice()處理器根據(jù)Predicate1Predicate2的值將傳入消息定向到Target1蠢琳,Target2Target3

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:foomock: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");
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市救湖,隨后出現(xiàn)的幾起案子愧杯,更是在濱河造成了極大的恐慌,老刑警劉巖鞋既,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件力九,死亡現(xiàn)場離奇詭異耍铜,居然都是意外死亡,警方通過查閱死者的電腦和手機畏邢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門业扒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人舒萎,你說我怎么就攤上這事程储。” “怎么了臂寝?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵章鲤,是天一觀的道長。 經(jīng)常有香客問我咆贬,道長败徊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任掏缎,我火速辦了婚禮皱蹦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘眷蜈。我一直安慰自己沪哺,他們只是感情好,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布酌儒。 她就那樣靜靜地躺著辜妓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪忌怎。 梳的紋絲不亂的頭發(fā)上籍滴,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機與錄音榴啸,去河邊找鬼孽惰。 笑死,一個胖子當著我的面吹牛鸥印,可吹牛的內(nèi)容都是我干的灰瞻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼辅甥,長吁一口氣:“原來是場噩夢啊……” “哼酝润!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起璃弄,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤要销,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后夏块,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疏咐,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡纤掸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了浑塞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片借跪。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖酌壕,靈堂內(nèi)的尸體忽然破棺而出掏愁,到底是詐尸還是另有隱情,我是刑警寧澤卵牍,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布果港,位于F島的核電站,受9級特大地震影響糊昙,放射性物質(zhì)發(fā)生泄漏辛掠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一释牺、第九天 我趴在偏房一處隱蔽的房頂上張望萝衩。 院中可真熱鬧,春花似錦没咙、人聲如沸欠气。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至队塘,卻和暖如春袁梗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背憔古。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工遮怜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鸿市。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓锯梁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親焰情。 傳聞我的和親對象是個殘疾皇子陌凳,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容