如何在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
相关产品推荐
相关产品推荐

