端点
Camel 通过 Endpoint 接口支持消息端点(Message Endpoint)模式。
端点由组件(Component)创建,并在 DSL 中通过端点 URI 来引用。
示例
下面的示例路由通过 URI 演示了 File 消费端点和 * JMS 生产端点的使用:
- Java
- XML
- YAML
from("file:messages/foo")
.to("jms:queue:foo");<route>
<from uri="file:messages/foo"/>
<to uri="jms:queue:foo"/>
</route>- route:
from:
uri: file:messages/foo
steps:
- to:
uri: jms:queue:foo从端点引用 Bean
使用 URI 语法配置端点时,可以通过 #bean:id 表示法引用 Registry 中的 Bean。
仅使用 #id 的旧语法已被废弃,因为 Camel 支持多种以 # 开头的其他函数,会造成歧义。 |
|---|
如果 URI 参数值以 #bean: 开头,Camel 将在 Registry 中按 id 查找指定类型的 Bean。例如:
- Java
- XML
- YAML
from("file:messages/foo?sorter=#bean:mySpecialFileSorter")
.to("jms:queue:foo");<route>
<from uri="file:messages/foo?sorter=#bean:mySpecialFileSorter"/>
<to uri="jms:queue:foo"/>
</route>- route:
from:
uri: file:messages/foo
parameters:
sorter: "#bean:mySpecialFileSorter"
steps:
- to:
uri: jms:queue:foo将在 Registry 中查找 id 为 mySpecialFileSorter 的 bean。
按类引用 bean
Camel 还支持按类的类型来引用 bean,例如 #class:com.foo.MySpecialSorter,这样将会为给定的类名创建一个新的 bean 实例。
如果需要向构造函数提供参数,这也是可行的(仅限于数字、布尔值、字面量和 null 值)
file://inbox?sorter=#class:com.foo.MySpecialSorter(10, 'Hello world', true)| 只有在 Bean 的选项较少、代码易于理解和维护时,才建议内联构造函数参数。另外要注意,如果 Bean 的构造函数被重构,则相应的字符串文本也需要随之更新。 |
|---|
按类型引用 Bean
使用 URI 语法配置端点时,现在可以按类型引用 Bean,系统会根据给定的类型从 Registry 中查找对应的 Bean。
如果在注册表中找到一个该类型的 Bean,则会使用该 Bean 实例;否则将抛出异常。
例如,下面的配置期望 Registry 中存在一个 org.apache.camel.spi.IdempotentRepository 类型的 Bean,文件端点将使用它。
file://inbox?idempontentRepository=#type:org.apache.camel.spi.IdempotentRepository在 XML 中配置端点 URI(转义 & 符号)
如果你尝试在 XML DSL 中使用 Camel 的某个 URI,并采用 URI 查询参数的写法,例如:
<route>
<from uri="direct:start?paramA=1¶mB=2"/>
<to uri="mock:result"/>
</route>你可能会遇到如下错误……
Caused by: org.xml.sax.SAXParseException: The reference to entity "paramB" must end with the ';' delimiter.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:236)
at这是因为在 XML 中,你需要对某些特殊的 XML 字符进行转义,例如:
| 特殊字符 | 在 XML 中的转义方式 |
|---|---|
& | & |
< | < |
> | > |
因此,如果你编写如下 XML,它应该可以正常工作……
<route>
<from uri="direct:start?paramA=1&paramB=2"/>
<to uri="mock:result"/>
</route>如果不转义 & 符号,就会抛出 org.xml.sax.SAXParseException 或其他类型的 XML 解析错误。
在用于指定 Camel 端点的 URI 中,& 用于分隔参数。然而,& 同时也是 XML 中的保留字符。
因此,当使用 XML DSL 配置 Camel 路由时,必须将 URI 中的所有 & 替换为 &。
例如,下面是在 Java DSL 和 XML DSL 中的同一个端点 URI,其中 & 已被替换为 &:
- Java
- XML
from("timer://myTimer?fixedRate=true&delay=0&period=2000")<from uri="timer://myTimer?fixedRate=true&delay=0&period=2000"/>使用原始值(如密码)配置参数值
使用 URI 语法配置端点选项时,参数值默认会进行 URI 编码。如果你希望配置密码并直接原样使用该值而不进行任何编码,这就会成为一个问题。例如,密码中可能包含加号,默认情况下它会被编码为十进制转义。
你可以使用 RAW(value) 语法将参数值定义为原始值,即该值以 RAW( 开头,以右括号 ) 结尾。
下面是一个密码为 se+re?t&23 的小示例:
- Java
- XML
- YAML
- 展开的 YAML
from("file:inbox")
.to("ftp:joe@myftpserver.com?password=RAW(se+re?t&23)&binary=true");<route>
<from uri="file:inbox"/>
<to uri="ftp:joe@myftpserver.com?password=RAW(se+re?t&23)&binary=true"/>
</route>- route:
from:
uri: file:inbox
steps:
- to:
uri: ftp:joe@myftpserver.com?password=RAW(se+re?t&23)&binary=true- route:
from:
uri: file
parameters:
directoryName: inbox
steps:
- to:
uri: ftp
parameters:
host: joe@myftpserver.com
password: "RAW(se+re?t&23)"
binary: true在上面的示例中,我们将密码值声明为 raw,实际密码将按输入的原样使用,例如 se+re?t&23。
当你将 ) 和 & 字符同时用作密码的一部分时(例如 se+re)t&23),可能会遇到一种边界情况。解析器会把 ) 解释为 RAW 函数的结束,并认为后面是一个以 & 开头的参数。在这种情况下,你可以改用 RAW{} 表示法,以便包含 ) 字符并让它作为密码的一部分被解码(例如 RAW{se+re)t&23})。作为一种更安全的替代方案,你也可以使用 password=#property:myPass,然后将 myPass 设置为一个属性占位符值。 |
|---|
在 raw 值中使用环境变量
如果需要使用环境变量,例如作为用户名或密码,现在可以通过在 RAW(…) 中内联 Simple 语言、使用 $simple{xxx} 语法来实现,如下所示:
- Java
- XML
- YAML
from("file:inbox")
.to("ftp:joe@myftpserver.com?password=RAW($simple{env:MY_FTP_PASSWORD})&binary=true");<route>
<from uri="file:inbox"/>
<to uri="ftp:joe@myftpserver.com?password=RAW($simple{env:MY_FTP_PASSWORD})&binary=true"/>
</route>- route:
from:
uri: file:inbox
steps:
- to:
uri: ftp:joe@myftpserver.com
parameters:
password: "RAW($simple{env:MY_FTP_PASSWORD})"
binary: true使用属性占位符的端点 URI
Camel 对属性占位符提供了广泛的支持。
例如,在上面的 ftp 示例中,我们可以将密码外部化到 application.properties 文件中。
myFtpPassword=RAW(se+re?t&23)随后,Camel 路由即可使用 {{key}} 这种形式来引用该占位符。
- Java
- XML
- YAML
from("file:inbox")
.to("ftp:joe@myftpserver.com?password={{myFtpPassword}}&binary=true");<route>
<from uri="file:inbox"/>
<to uri="ftp:joe@myftpserver.com?password={{myFtpPassword}}&binary=true"/>
</route>- route:
from:
uri: file:inbox
steps:
- to:
uri: ftp:joe@myftpserver.com
parameters:
password: "{{myFtpPassword}}"
binary: true并拥有一个包含密码的 application.properties 文件。注意,我们仍然使用 RAW(value) 形式来确保密码被原样使用:
myFtpPassword=RAW(se+re?t&23)我们仍然可以在 Camel 路由中改用 RAW(value):
仅限 Java:在路由 URI 中内联使用 RAW()
.to("ftp:joe@myftpserver.com?password=RAW({{myFtpPassword}})&binary=true")接下来,我们需要从属性文件中删除 RAW:
myFtpPassword=se+re?t&23配置 CamelContext 默认缓存大小
CamelContext 默认会缓存最近使用的 1000 个端点(基于 LRUCache)。
必须在 CamelContext 上将其作为全局选项进行配置,如下方 Java 代码所示:
仅使用 Java:通过 CamelContext API 配置端点缓存大小
getCamelContext().getGlobalOptions().put(Exchange.MAXIMUM_ENDPOINT_CACHE_SIZE, "500");默认的最大缓存大小为 1000。
你需要在 CamelContext 启动之前完成此配置。
使用时、分语法配置时间间隔
Camel 的一些组件提供了用于指定时间间隔的选项,该时间间隔必须以毫秒为单位输入。
当数值较大时,例如 2700000 毫秒(45 分钟),这对人类阅读来说并不友好。
在 Camel 中,你可以使用更具可读性的语法来配置,说明如下:
| 语法 | 单位 |
|---|---|
| h | 小时 |
| m | 分钟 |
| s | 秒 |
例如,Timer 端点可以按如下方式配置:
- Java
- XML
- YAML
from("timer:foo?period=45m").to("log:foo");<route>
<from uri="timer:foo?period=45m"/>
<to uri="log:foo"/>
</route>- route:
from:
uri: timer:foo?period=45m
steps:
- to:
uri: log:foo你可以混合搭配这些单位,因此也可以这样写:
- Java
- XML
- YAML
from("timer:foo?period=1h15m").to("log:foo");
from("timer:bar?period=2h30s").to("log:bar");
from("timer:bar?period=3h45m58s").to("log:bar");<route>
<from uri="timer:foo?period=1h15m"/>
<to uri="log:foo"/>
</route>
<route>
<from uri="timer:bar?period=2h30s"/>
<to uri="log:bar"/>
</route>
<route>
<from uri="timer:bar?period=3h45m58s"/>
<to uri="log:bar"/>
</route>- route:
from:
uri: timer:foo?period=1h15m
steps:
- to:
uri: log:foo
- route:
from:
uri: timer:bar?period=2h30s
steps:
- to:
uri: log:bar
- route:
from:
uri: timer:bar?period=3h45m58s
steps:
- to:
uri: log:bar不过,你也可以使用长语法:
| 语法 | 单位 |
|---|---|
| hour 或 hours | 小时 |
| minute 或 minutes | 分钟 |
| second 或 seconds | 秒 |
- Java
- XML
- YAML
from("timer:foo?period=45minutes").to("log:foo");<route>
<from uri="timer:foo?period=45minutes"/>
<to uri="log:foo"/>
</route>- route:
from:
uri: timer:foo?period=45minutes
steps:
- to:
uri: log:fooJava Endpoint API
你几乎从不需要通过 Java API 手动创建端点。
通过 Endpoint,你可以使用以下 Java API 方法为该端点创建生产者或消费者:
createProducer()会创建一个 Producer,用于向该端点发送消息交换(Exchange)。createConsumer()实现了事件驱动消费者(Event Driven Consumer)模式,在创建 Consumer 时通过 Processor 从该端点消费消息交换。createPollingConsumer()实现了轮询消费者(Polling Consumer)模式,通过 PollingConsumer 从该端点消费消息交换。
评论
登录后参与评论
KnowForge