规则引擎(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 

posted @ 2020-08-26 14:01  小窝蜗  阅读(952)  评论(0编辑  收藏  举报