【问题标题】:Split a List of Lists with camel splitter使用骆驼拆分器拆分列表列表
【发布时间】:2019-01-31 22:45:25
【问题描述】:

我创建了许多 ArrayList 来保存单独实体的集合,这些集合被拆分为它们自己的实体。这些被添加到 ArrayList 然后推送到我尝试拆分列表列表的交换。我似乎无法拆分列表列表。

尝试了拆分器的许多变体,使用令牌等。

List<String> serviceRecords = new ArrayList<String>();  //holds an assets collection
List<String> toRecords = new ArrayList<String>();       //holds all asset collections

在收集属于一个组的项目后,将它们添加到一个 ArrayList 中。

serviceRecords.add(sb.toString());

添加完所有项目后,列表将添加到列表中。

toRecords.addAll(serviceRecords);

然后我将列表推送到交易所

exchange.getIn().setBody(toRecords);

然后是 XML 路由,它在尝试不同的东西时处于混乱状态。这些都不起作用。拆分List of Lists一定有技巧。

    <route autoStartup="true" id="core.fleet.asset.splitterRoute">
        <from id="_from4" uri="{{fileEnrichmentEndpoint}}"/>
        <process id="_process4" ref="assetCollectorProcessor"/>
        <process id="_process5" ref="fleetAssetSplitter"/>
        <split id="FleetSplit">    <!-- strategyRef="tsAggregationStrategy" -->
        <!-- <simple>${body}</simple> -->
        <tokenize token="BLOCKMarker"/>
          <log id="splitBody" message="Split Body: ${body}"/>
          <to id="_splitOut" uri="{{fileSplitDestination}}/?fileName=GCMS_asset_${date:now:yyyyMMddhhmmss}.csv"/>
          <!-- <process id="getName" ref="fleetAssetFileName"/> -->
          <!-- <to id="_splitOut" uri="{{fileSplitDestination}}/?fileName=GCMS_asset_${date:now:yyyyMMdd}.csv"/> -->
        </split>
        <!-- <to id="_splitOut" uri="{{fileSplitDestination}}/?fileName=GCMS_asset_${date:now:yyyyMMdd}.csv"/> -->
        <stop/>
    </route>

List of Lists 拆分生成的多个文件。

【问题讨论】:

  • 什么是“交换”对象?它的类型是什么?您要拆分什么对象以及要根据什么属性拆分它?

标签: java arraylist split apache-camel splitter


【解决方案1】:

您可以根据需要使用 JavaBean 来实现嵌套的 Splitter 逻辑。

如果标准Splitter EIP不能做你想做的事,你可以用一个bean告诉他如何分割你的消息的有效负载。

因此,如果您将 Splitter 配置为使用您的自定义 bean

from("direct:split")
    .log("Original body: ${body}")
    .split().method(new SplitterBean(), "splitServiceRecords")
    .log("Message part: ${body}")
    .to("mock:end");

bean 只是在结果列表中收集所有服务记录(来自您的示例)

public List<String> splitServiceRecords(List<List<String>> body) {
    List<String> collectedServiceRecords = new ArrayList<String>();
    // iterate over List containing lists and add each item of
    // the inner list to the Splitter result
    for (List<String> serviceRecords : body) {
        for (String serviceRecord : serviceRecords) {
            collectedServiceRecords.add(serviceRecord);
        }
    }
    return collectedServiceRecords;
}

List of Lists 将成为一个包含所有项目的单个列表,每个项目成为一个消息,由 Camel 进一步路由。

以上路线的日志输出:

INFO: Original body: [[Foo, Bar, Baz], [Record, item, thing]]
...
INFO: Message part: Foo
INFO: Message part: Bar
INFO: Message part: Baz
INFO: Message part: Record
INFO: Message part: item
INFO: Message part: thing

【讨论】:

  • 谢谢,是的,我刚买了新的 Camel 书。看起来我需要合并一个聚合器——我可以并且已经成功地实现了基于单个 ArrayList、CSV、组和标记化的拆分器。我只是需要一个列表列表——一个包含许多 ArrayList 并遇到障碍的 ArrayList——在这种安排中似乎需要做一些特殊的事情。
  • 我添加了一个拆分列表列表的示例,以便内部列表的每个项目都成为一条消息。
  • 谢谢 burki,太好了!我想在阅读了书中的部分之后,我仍然感到困惑。我将在上面尝试您的解决方案。我看到的是 spltter 正在拆分整个数组列表。从日志看来,列表列表被拆分为一条消息。我期待拆分器迭代器迭代列表并拆分其中的列表。它似乎不以这种方式工作。
  • Burki,我需要保持内部容器 (ArrayLists) 作为单独的实体,然后将这些内部数组列表拆分出来。每个内部列表都包含一个唯一的实体。我希望这是有道理的。
【解决方案2】:

我不知道天气该删除这个还是为了其他人的兴趣而离开。
在发现我使用了错误的 List 方法后,List.addAll() 而不是 List.add(object) 并进行了此更正,我的错,令人惊讶的是,在其领域中的所有内容都按预期的理论预期工作,它可以工作。

所以这很简单。您不需要做任何特别的事情来拆分列表列表。 拆分器将遍历列表并拆分出各个列表。然后,您可以掌握这些列表并处理它们并转发它们。认为成熟的 Camel Splitter EIP 行为怪异,我觉得很愚蠢,它正在做它应该做的事情。

这是最终结果。 (感谢 burki 等人的帮助)

    <route autoStartup="true" id="core.fleet.asset.splitterRoute">
        <from id="_from4" uri="{{fileEnrichmentEndpoint}}"/>
        <process id="_process4" ref="assetCollectorProcessor"/>
        <process id="_process5" ref="fleetAssetSplitter"/>
        <split id="fs1">
            <simple>${body}</simple>
            <log id="lfs1" message="Original Body: ${body}"/>
            <process id="pfs1" ref="fileSplitter" />
            <to id="seda:fs1" uri="seda:fs1"/>
        </split>
    </route>

我将文件名隐藏在位置 -0- 的内部列表列表中,因此我们只需提取文件名,设置 CamelFileName,稍微处理一下数据并将其发送到交易所。

    log.info("File Splitter :: Start");

    List<String> pl = (List<String>) exchange.getIn().getBody(List.class);
    log.info("File Pay Load: " + pl);

    fName = pl.get(0);  //get file name
    exchange.getIn().setHeader("CamelFileName", fName);
    pl.remove(0);
    log.debug("**** serviceRecords  ****");
    Iterator<String> pitr = pl.iterator(); 
    while ( pitr.hasNext()) {
          log.debug(pitr.next());
      }
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    DataOutputStream out = new DataOutputStream(baos);
    for (String record : pl) {
        out.writeBytes(record + System.lineSeparator());
    }
    out.flush();
    exchange.getIn().setBody(baos.toByteArray());
    out.close();

    log.info("File Splitter :: Finish");

【讨论】:

    【解决方案3】:

    你只需要在RouterBuilder配置中拆分两次

    from("direct:split")
        .split(body())
        .split(body())
        .log("Message part: ${body}")
        .to("mock:end");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-17
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多