camel系列-消息路由器(route)

概念

问题

在管道和过滤器链中,多个处理步骤是通过消息通道连接起来的。

如何才能对各个处理步骤解耦合,使消息能按照一组条件传递到不同的过滤器?

解决方案

插入一个特殊的过滤器,即消息路由器,它从一个消息通道中消费一个消息,然后根据一组条件把它重新发布到不同的消息通道中。

camel 示例

Route 定义

RouteBuilder

RouteBuilder 用于创建 Route 对象

1
2
3
4
5
6
7
8
public class FileCopyRouteBuilder extends RouteBuilder
{
@Override
public void configure() throws Exception {
from("file:/data/inbox?noop=true")
.to("file:/data/outbox");
}
}

from 和 to 分别代表一个消息端点,消息端点使用URI进行创建

端点 URL

Camel 端点的 URI 由三个部分组成:方案(Scheme)、上下文路径(Context Path)和参数(Option)列表

运行 Camel

以下是一个完整的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String args[]) throws Exception {
// create CamelContext
CamelContext context = new DefaultCamelContext();

// add our route to the CamelContext
context.addRoutes(new FileCopyRouteBuilder());

// start the route and let it do its work
context.start();
Thread.sleep(10000);

// stop the CamelContext
context.stop();
}
  1. 初始化一个 CamelContext 实例,类似 Spring 的 ApplicationContext,先不用理解其细节
  2. 并调用 addRoutes 添加 RouteBuilder
  3. 调用 start 方法,开始工作
  4. 执行完毕之后调用 stop 方法,释放 CamelContext 上下文环境

以上就是一个完整 Camel 的运行示例

路由器类别

Multicast(消息广播)

将消息路由到多个消息端点

示例

1
2
3
4
5
6
7
8
9
<route>
<from uri="direct:start"/>
<multicast stopOnException="true">
<to uri="direct:foo"/>
<to uri="direct:bar"/>
<to uri="direct:baz"/>
</multicast>
<to uri="mock:result"/>
</route>

Filter(消息过滤)

问题

如何避免组件接收到与之无关的消息?

解决方案

使用一种特殊的消息路由器:消息过滤器,可以根据一组规则把不需要的消息从通道中剔除。

示例

1
2
3
from("direct:a")
.filter(simple("${header.foo} == 'bar'"))
.to("direct:b");

基于内容的路由器

问题

如果一个逻辑功能的实现需要跨越多个物理系统,这种情况应该如何应对?

解决方案

使用基于内容的路由器,根据消息的内容把每条消息路由给正确的接收者。

示例

1
2
3
4
5
6
7
8
from("direct:a")
.choice()
.when(simple("${header.foo} == 'bar'"))
.to("direct:b")
.when(simple("${header.foo} == 'cheese'"))
.to("direct:c")
.otherwise()
.to("direct:d");

WireTap(线路分接器)

如何检查点对点通道中传输的消息?

在通道中插入线路分接器,这是一个简单的接收表,能够把到来的各个消息同时发布到主通道和副通道中。

1
2
3
4
from("direct:start")
.to("log:foo")
.wireTap("direct:tap")
.to("mock:result");

参考