预测
然后,表达式和谓词可用于在 DSL 中创建各种企业集成模式,如基于内容的路由器 EIP。
为支持动态规则,Camel 支持使用各种不同语言的可插入谓词策略。
预设 API
如图所示,骆驼谓词的 API 定义在 org.apache.camel.Predicate
接口中:
public interface Predicate {
/**
* Evaluates the predicate on the message exchange and returns true if this
* exchange matches the predicate
*
* @param exchange the message exchange
* @return true if the predicate matches
*/
boolean matches(Exchange exchange);
}
Predicate
正在被求值为布尔值,因此结果要么是 true
,要么是 false
。.这使得谓词功能强大,因为它经常被用来控制信息的路由路径。
一个简单的例子是使用基于内容的路由器 EIP 根据报头值路由 Exchange:
from("jms:queue:order")
.choice()
.when(header("type").isEqualTo("widget")).to("bean:widgetOrder")
.when(header("type").isEqualTo("wombat")).to("bean:wombatOrder")
.otherwise()
.to("bean:miscOrder")
.end();
在上面的路径中,谓词是 header("type").isEqualTo("widget")
,因为它是作为一个表达式构建的,而表达式又是作为一个谓词进行评估的。为此,各种构建器类帮助我们创建了一种漂亮流畅的语法。 isEqualTo
是一个构建器方法,可根据输入返回一个谓词。
有时,流畅构建器会变得很长,读起来有点复杂,这时你可以在路由之外定义谓词,然后在路由中引用谓词即可:
Predicate isWidget = header("type").isEqualTo("widget");
然后你就可以在路径中将其称为"......":
from("jms:queue:order")
.choice()
.when(isWidget).to("bean:widgetOrder")
.when(isWombat).to("bean:wombatOrder")
.otherwise()
.to("bean:miscOrder")
.end();
否定谓语
您可以使用 PredicateBuilder
的 not 方法来否定谓词。
首先,我们导入静态方法 not
这样,我们的路由就变得清晰易读了:
import static org.apache.camel.builder.PredicateBuilder.not;
然后,我们可以用它来包围一个已有的谓词并否定它,如示例所示:
from("direct:start")
.choice()
.when(not(header("username").regex("goofy|pluto"))).to("mock:people")
.otherwise().to("mock:animals")
.end();
复合谓词
您还可以使用布尔操作符(如 and, or, not
等)创建复合谓词。
目前,这一功能只适用于基于 Java 的 DSL,而不适用于 XML 等其他 DSL。
使用 PredicateBuilder
类,您可以根据逻辑运算符和比较运算符组合来自不同表达式语言的谓词:
-
not
,and
,or
-
isNull
,isNotNull
-
isEqualTo
,isGreaterThan
,isLessThan
-
startsWith
,endsWith
-
in
(X谓词中的任何一个为真")。
此外,您还可以使用 PredicateBuilder
创建正则表达式,并将其用作谓词,应用于表达式的结果,例如
PredicateBuilder.regex(header("foo"), "\d\{4}");
将正则表达式应用于 foo 头信息。
还可以将不同的表达语言组合起来,例如
PredicateBuilder.and(XPathBuilder.xpath("/bookings/flights"), simple("${exchangeProperty.country = 'Spain'}"))
下面的示例展示了更多的使用案例:
// We define 3 predicates based on some user roles
// we have static imported and/or from org.apache.camel.builder.PredicateBuilder
// First we have a regular user that is just identified having a username header
Predicate user = header("username").isNotNull();
// The admin user must be a user AND have a admin header as true
Predicate admin = and(user, header("admin").isEqualTo("true"));
// And God must be an admin and (either have type god or a special message containing Camel Rider)
Predicate god = and(admin, or(body().contains("Camel Rider"), header("type").isEqualTo("god")));
// As you can see with the predicates above we can stack them to build compound predicates
// In our route below we can create a nice content based router based on the predicates we
// have defined. Then the route is easy to read and understand.
// We encourage you to define complex predicates outside the fluent router builder as
// it will just get a bit complex for humans to read
from("direct:start").choice()
.when(god).to("mock:god")
.when(admin).to("mock:admin")
.when(user).to("mock:user")
.otherwise().to("mock:guest")
.end();