提问者:小点点

如何将两条消息与Apache Camel中从MySQL数据库检索到的数据相结合?


我目前正在从事一个集成项目。我必须从MySQL数据库中获取一些数据,并使用Apache Camel将它们组合起来。在数据库中,我有两个表,分别是materials和packages。它们是一对多关系,一种材料可以包含多个包装。我已经知道如何从数据库中获取数据并将其保存到json文件中,但我不知道如何将这两条消息合并为一条。我读过关于聚合的文章,但我并不真正了解它们。这是我第一次使用Apache Camel,我真的不知道现在该怎么做。这些路由的代码如下所示:

public class InputAdapter{

public static void main(String[] args) throws Exception {

    BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://localhost:3306/Packages");
    dataSource.setUsername("uname");
    dataSource.setPassword("passwd");
    SimpleRegistry registry = new SimpleRegistry();
    registry.bind("dataSource", dataSource);

    CamelContext context = new DefaultCamelContext(registry);
    context.addRoutes(new RouteBuilder() {
        @Override
        public void configure() {
            from("timer://foo?repeatCount=1")
                    .setBody(constant("SELECT * FROM material;"))
                    .to("jdbc:dataSource")
                    .marshal().json(true)
                    .to("file:/some/path/to/file?fileName=materials.json");
            from("timer://foo?repeatCount=1")
                    .setBody(constant("SELECT * FROM package;"))
                    .to("jdbc:dataSource")
                    .marshal().json(true)
                    .to("file:/some/path/to/file?fileName=packages.json");
        }
    });

    context.start();
    Thread.sleep(10000);
    context.stop();
}
}

材质和包的模型只是具有getter和setter的私有属性:

public class Material {
private int id;
private int number;
private enumType type;
private String name;
private String description;
private boolean is_deleted;
private List<Package> packageList = new ArrayList<>();

public enum enumType {
    A1, A2, A3, B1, B2, B3, Z1, Z2, Z3;
}

public int getId() {
    return this.id;
}

... some getters
}

public List<Package> getPackageList() {
    return this.packageList;
}

public void setId(int id) {
    this.id = id;
}

... some setters

public void setPackageList(List<Package> packages) {
    this.packageList = packages;
}
}

谁能给我一个提示,我现在该怎么办?请帮帮我。


共1个答案

匿名用户

聚合器通常用于合并来自某个源的消息。我可能不会使用聚合器来组合这两组项目。如果您希望提取所有材质并从数据库中获取关联的包,那么最好检索每个材质的包列表。

我将创建一个处理器来处理检索每个返回材料对象的包,然后在单个路由中输出整个内容。

您可以在Camel中定义一个处理器类,如下所示:

public class PackageProcessor implements Processor {
  @Override
  public void process(Exchange exchange) {
    // Transform the input to your message class
    // Retrieve the Packages
    // Transform the results to Packages
    // Add to the Material
    // Set the Out Body
    exchange.getMessage().setBody(material);
  }
}

然后,您可以使用路由中的处理器来执行此工作。这将使路由看起来像这样:

from("timer://foo?repeatCount=1")
  .routeId("my-material-route")
  .setBody(constant("SELECT * FROM materials;"))
  .to("jdbc:dataSource")
  .split(body())
  .process(new PackageProcessor())
  .setHeader(Exchange.FILE_NAME, simple("${exchangeId}.json"))
  .marshal().json(true)
  .to("file:/somepath")
  .end();

这将把每条记录输出到一个包含所需信息的Json文件中。如果您想将所有项目都放在一个文件中,这就是聚合器发挥作用的地方。

您会注意到路由中的几个项目超出了您的原始路由。JDBC组件的结果是一个ArrayList

处理器完成后,我们将exchange上的CamelFileName头设置为exchange Id,然后这将从Materials表中为每条记录输出一个单独的文件。

如果您想将所有内容都包含在一个文件中,您可以使用聚合器来收集交换并构建列表。让它将交换释放到JSON文件中可能会稍微复杂一点。您通常必须设置超时或某种评估函数来确定何时应该释放“超级”交换。