规则引擎(Apache camel) 学习四
1.Routing路由条件
介绍:在控制端点和处理器之间、处理器和处理器之间,Camel允许开发人员进行路由条件设置。
例如开发人员可以拥有当Exchange In Message的内容为A的情况下将消息送入下一个处理器A,
当Exchange In Message的内容为B时将消息送入下一个处理器B的处理能力。
又例如,无论编排的路由中上一个元素的处理消息如何,都将携带消息的Exchange对象复制 多份,
分别送入下一处理器X、Y、Z。开发人员甚至还可以通过路由规则完成Exchange到多个Endpoint的负载传输。
路由规则:
Camel中支持的路由规则非常丰富,包括:Message Filter、Based Router、Dynamic Router、
Splitter、Aggregator、Resequencer等等。
在Camel的官方文档中使用了非常形象化的图形来表示这些路由功能.
实际上EIP规则中所描述的大部分业务集成模式,在以上页面都能找到对应的图形化表达。
2.Content Based Router 基于内容的路由(路由规则)
介绍:把Content Based Router译为基于内容的路由,笔者觉得更为贴切(并不能译作基本路由,实际上你无法定义什么是基本路由)。
它并不是一种单一的路由方式,而是多种基于条件和判断表达式的路由方式。
其中可能包括choice语句/方法、when语句/方法、otherwise语句/方法。
实现:
package com.yinwenjie.test.cameltest.helloworld;
......
/**
* 使用条件选择进行路由编排
* @author yinwenjie
*/
public class ChoiceCamel extends RouteBuilder
{
public static void main(String[] args) throws
Exception {
// 这是camel上下文对象,整个路由的驱动全靠它了。
ModelCamelContext camelContext = new DefaultCamelContext();
// 启动route
camelContext.start();
// 将我们编排的一个完整消息路由过程,加入到上下文中
camelContext.addRoutes(new ChoiceCamel());
// 通用没有具体业务意义的代码,只是为了保证主线程不退出
synchronized (ChoiceCamel.class) {
ChoiceCamel.class.wait();
}
}
@Override
public void configure() throws Exception {
// 这是一个JsonPath表达式,用于从http携带的json信息中,提取orgId属性的值
JsonPathExpression jsonPathExpression = new
JsonPathExpression("$.data.orgId");
jsonPathExpression.setResultType(String.class);
// 通用使用http协议接受消息
from("jetty:http://0.0.0.0:8282/choiceCamel")
// 首先送入HttpProcessor,
// 负责将exchange in Message Body之中的stream转成字符串
// 当然,不转的话,下面主要的choice操作也可以运行
// HttpProcessor中的实现和上文代码片段中的一致,这里就不再重复贴出
.process(new HttpProcessor())
// 将orgId属性的值存储 exchange in Message的header中,以便后续进行判断
.setHeader("orgId", jsonPathExpression)
.choice()
// 当orgId == yuanbao,执行OtherProcessor
// 当orgId == yinwenjie,执行OtherProcessor2
// 其它情况执行OtherProcessor3
.when(header("orgId").isEqualTo("yuanbao"))
.process(new OtherProcessor())
.when(header("orgId").isEqualTo("yinwenjie"))
.process(new OtherProcessor2())
.otherwise()
.process(new OtherProcessor3())
// 结束
.endChoice();
}
/**
* 这个处理器用来完成输入的json格式的转换
* 和上一篇文章出现的HttpProcessor 内容基本一致。就不再贴出了
* @author yinwenjie
*/
public class HttpProcessor implements Processor
{
......
}
/**
* 另一个处理器OtherProcessor
* @author yinwenjie
*/
public class OtherProcessor implements Processor
{
@Override
public void process(Exchange exchange) throws
Exception {
Message message = exchange.getIn();
String body = message.getBody().toString();
// 存入到exchange的out区域
if(exchange.getPattern() == ExchangePattern.InOut)
{
Message outMessage = exchange.getOut();
outMessage.setBody(body + " || 被OtherProcessor处理");
}
}
}
/**
* 很简单的处理器OtherProcessor2
* 和OtherProcessor基本相同,就不再重复贴出
* @author yinwenjie
*/
public class OtherProcessor2 implements Processor
{
......
outMessage.setBody(body + " || 被OtherProcessor2处理");
}
/**
* 很简单的处理器OtherProcessor3
* 和OtherProcessor基本相同,就不再重复贴出
* @author yinwenjie
*/
public class OtherProcessor3 implements Processor
{
......
outMessage.setBody(body + " || 被OtherProcessor3处理");
}
}
总结:以上代码片段中,开发人员首先使用JsonPath表达式,从Http中携带的json信息中寻找到orgId这个属性的值,
然后将这个值存储在Exchange的header区域(这样做只是为了后续方便判断,您也可以将值存储在Exchange的properties区域,
还可以直接使用JsonPath表达式进行判断) 。接下来,通过判断存储在header区域的值,
让消息路由进入不同的Processor处理器。由于我们设置的from-jetty-endpoint中默认的Exchange Pattern值为InOut,
所以在各个Processor处理器中完成处理后 Out Message的Body内容会以Http响应结果的形式返回到from-jetty-endPoint中。
最后我们将在测试页面上看到Processor处理器中的消息值。
Camel中支持绝大多数被开发人员承认和使用的表达式:正则式、XPath、JsonPath等。
如果各位读者对JsonPath的语法还不熟悉的话,可以参考Google提供的说明文档(https://code.google.com/p/json-path/)。
为了测试以上代码片段的工作效果,我们使用Postman工具向指定的地址发送一段json信息,并观察整个路由的执行效果。
如下图所示:
当orgId的值为yuanbao时的执行效果
总结:
当orgId的值为yinwenjie时的执行效果
关于路由判断,Camel中提供了丰富的条件判断手段。除了我们在本小节中使用的isEqualTo方式还包括:
isGreaterThan、isGreaterThanOrEqualTo、isLessThan、isLessThanOrEqualTo、isNotEqualTo、in(多个值)、contains、regex等等,
它们的共同点是这些方法都返回某个实现了org.apache.camel.Predicate接口的类。
学习来源:http://www.uml.org.cn/zjjs/201801222.asp?artid=20340