You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Apache Camel中用一个API的返回参数调用另一个API?

问题描述

我已经通过Apache Camel调用并反序列化了一个REST API,现在需要使用该API返回的编号作为参数调用另一个API。我尝试了如下实现方式:

public Collection<String> nos;
 
from("direct:further").tracing()
       .log("body: " + body().toString())
       .setBody().constant(null)
       .setHeader("CamelHttpMethod")
       .simple("GET")
       .setHeader("Authorization")
       .simple("Bearer "+"${header.jwt}")
       .to("https://call/api/that/returns/numbers")
       .choice()
       .when().simple("${header.CamelHttpResponseCode} == 200").unmarshal().json(JsonLibrary.Jackson, Abc.class)
.process(
           ex->{
             Quantity quantity = ex.getIn().getBody(Abc.class);
             List<Variations> variationsList = Arrays.stream(quantity.getResources().getVariations()).toList();
             nos=variationsList.stream().map(Variations::getNo).collect(
                 Collectors.toList());
nos.forEach(s -> { //Since nos is a collection of String I would like to iterate through it
     
    String url="https://call/another/api/with/number"+"?"+s;//the link with the number as the parameter 
              from("direct:start")   //This is not working. I not able to call the url
                  .setHeader("CamelHttpHeader")
                    .simple("GET")
                    .setHeader("Authorization")
                    .simple("Bearer "+"${header.jwt}")
                    .log("I did call the numbers") //This is also not getting printed
                  .to(url);
});
 }).log("I am out of the loop" + body())
       .otherwise()
       .log("Error!!!");

但我无法成功调用第二个API,也尝试了以下写法:

from("rest:get:"+url).tracing()
    .setHeader("CamelHttpHeader")
    .simple("GET")
    .setHeader("Authorization")
    .simple("Bearer "+"${header.jwt}")
    .log("I did call the numbers").to(url);

同样无法在循环中正常工作。我在方法外部声明了集合nos,请问该如何通过nos中的编号调用另一个API?应在Lambda函数内部还是外部调用?

解决方案

你的核心错误是在process处理器里用from()定义路由——from()是用来初始化Camel路由的,不是用来在运行时触发HTTP调用的。下面提供两种正确的实现方式:

方法1:使用ProducerTemplate在process中直接调用

在Camel的处理器中,可以通过ProducerTemplate来同步调用另一个API,这是最直接的方式:

// 避免全局变量,改用局部变量处理集合
from("direct:further").tracing()
    .log("body: ${body}")
    .setBody(constant(null))
    .setHeader("CamelHttpMethod", simple("GET"))
    .setHeader("Authorization", simple("Bearer ${header.jwt}"))
    .to("https://call/api/that/returns/numbers")
    .choice()
        .when(simple("${header.CamelHttpResponseCode} == 200"))
            .unmarshal().json(JsonLibrary.Jackson, Abc.class)
            .process(exchange -> {
                Abc quantity = exchange.getIn().getBody(Abc.class);
                List<String> nos = Arrays.stream(quantity.getResources().getVariations())
                                        .map(Variations::getNo)
                                        .collect(Collectors.toList());
                
                // 获取ProducerTemplate实例用于触发HTTP调用
                ProducerTemplate template = exchange.getContext().createProducerTemplate();
                // 准备请求头
                Map<String, Object> headers = new HashMap<>();
                headers.put("CamelHttpMethod", "GET");
                headers.put("Authorization", "Bearer " + exchange.getIn().getHeader("jwt"));
                
                nos.forEach(no -> {
                    String url = "https://call/another/api/with/number?" + no;
                    // 同步调用API并获取返回结果
                    Object response = template.requestBodyAndHeaders(url, null, headers);
                    // 可在此处理返回结果,比如打印日志
                    log.info("Called API for number: {},response: {}", no, response);
                });
            })
            .log("Completed all API calls")
        .otherwise()
            .log("Error!!! Response code: ${header.CamelHttpResponseCode}");

方法2:使用Split组件拆分集合并调用

Camel的split组件可以自动遍历集合,每个元素单独处理,这种方式更符合Camel的路由风格,无需手动循环:

from("direct:further").tracing()
    .log("body: ${body}")
    .setBody(constant(null))
    .setHeader("CamelHttpMethod", simple("GET"))
    .setHeader("Authorization", simple("Bearer ${header.jwt}"))
    .to("https://call/api/that/returns/numbers")
    .choice()
        .when(simple("${header.CamelHttpResponseCode} == 200"))
            .unmarshal().json(JsonLibrary.Jackson, Abc.class)
            // 把编号集合提取到消息体中
            .process(exchange -> {
                Abc quantity = exchange.getIn().getBody(Abc.class);
                List<String> nos = Arrays.stream(quantity.getResources().getVariations())
                                        .map(Variations::getNo)
                                        .collect(Collectors.toList());
                exchange.getIn().setBody(nos);
            })
            // 拆分集合中的每个编号,逐个处理
            .split(body())
                .streaming() // 集合较大时启用流式处理,减少内存占用
                .setHeader("CamelHttpMethod", simple("GET"))
                .setHeader("Authorization", simple("Bearer ${header.jwt}"))
                // 动态设置目标URL
                .setHeader(Exchange.HTTP_URI, simple("https://call/another/api/with/number?${body}"))
                .to("https://dummy.url") // 占位符,实际使用header中的HTTP_URI
                .log("Called API for number: ${body},response code: ${header.CamelHttpResponseCode}")
            .end() // 结束split处理
            .log("Completed all API calls")
        .otherwise()
            .log("Error!!! Response code: ${header.CamelHttpResponseCode}");
关键注意事项
  • 避免全局变量nos:全局变量在多线程环境下存在线程安全问题,尽量在处理器内部处理集合。
  • 禁止运行时调用from():from()是路由定义阶段的方法,运行时调用不会生效,必须用ProducerTemplate或Camel组件(如split)触发调用。
  • 动态URL处理:第二种方法中通过Exchange.HTTP_URI头覆盖to()中的静态URL,实现动态调用。

内容的提问来源于stack exchange,提问作者Jeet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 00:35:30