2016-10-18 11 views
2

我正在接收Jetty Http端点上的请求。请求主体包含请求主体中的一些URL。我必须向这些网址发送GET请求。然后汇总每个GET请求的结果并将其返回给调用者。骆驼 - 使用Java DSL并行GET请求并通过动态路由汇总结果

请求正文: - 我能想到这样做的

{ 
    "data" : [ 
     {"name" : "Hello", "url" : "http://server1"} 
     {"name" : "Hello2", "url" : "http://server2"} 

    ] 
} 

一种方法是象下面这样: -

from("jetty:http://localhost:8888/hello").process(new Processor() { 
    public void process(Exchange exchange) throws Exception { 
     // 1. Make the GET request in parallel using ThreadPoolExecutor 
     // 2. Wait for all calls to finish. Collate the response 
     // 3. Write it to exchange.getOut().setBody 
    } 
}) 

有一个人可以让我知道这是否可以通过Java DSL使用来实现骆驼动态路线,Splitter & Aggregator让Processor保持相对较小?

我使用骆驼2.16.3。

+0

从概念上讲,您可以拆分原始邮件,以便每封新邮件都有一个URL。这些分割请求可以通过一些处理器。之后,你可以放置一个聚合器。我想多个消息可以传入初始消费者,因此您需要弄清楚如何确定哪些URL属于哪个URL组。 –

+0

你是从处理器建议我应该进行HTTP调用或连接处理器与一些'()'? – tuk

+0

不一定。我以这种方式构建它,因为你的例子展示了一个处理器执行GET操作。您可以使用骆驼组件之一:http,http4,甚至cxfrs或spring-ws,...以最简单的方式满足您的需求。 –

回答

2

的步骤是:

  1. 分割输入数据到网址。这可能涉及子步骤:对于 实例,您可能会将传入的JSON字符串解组到一些POJO中,也许此POJO有一个数组或列表,其中每个条目都是一个URL。然后,你可以把它作为身体传递。 (当然,您可能需要来自传入请求的其他信息,因此您可能会改变这一点。)
  2. 如果主体是数组或其他可轻松处理的分隔符,则分隔符会很容易分割。在最简单的情况下,分离器会在每个拆分消息的主体中传递一个URI。
  3. 接下来 - 在分流器的流程中 - 你可以有一个像http4这样的生产者,但是不要在端点上使用URI,而是要求它使用消息中的URI。
  4. 最后,你会有一个聚合器。

听起来像你的问题的核心是关于动态URI。这是一个代码段可能如下:

from(...)... etc. 
    .setHeader(Exchange.HTTP_URI, simple("${body}")) 
    .setHeader(Exchange.HTTP_METHOD, 
       constant(org.apache.camel.component.http4.HttpMethods.GET)) 
    .to("http4://google.com") 

对于一个小的工作演示,see this class

public class HttpDynamicClient extends RouteBuilder { 

    @Override 
    public void configure() throws Exception { 

     from("direct:testMultiple") 
     .split(body()) 
     .to("direct:httpClient"); 

     from("direct:httpClient") 
     .log("starting httpClient route") 
     .setHeader(Exchange.HTTP_URI, simple("${body}")) 
     .setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http4.HttpMethods.GET)) 
     .to("http4://google.com") 
     .process(new BodyToStringConverter()) 
     .log(LoggingLevel.INFO, "Output was ${body}"); 
    } 

    private static class BodyToStringConverter implements Processor { 
     @Override 
     public void process(Exchange exchange) throws Exception { 
      exchange.getOut().setBody(exchange.getIn().getBody(String.class)); 
     } 
    } 


    public static void main(String[] args) throws Exception { 
     CamelContext context = new DefaultCamelContext(); 
     try { 
      Logger logger = Logger.getLogger(HttpDynamicClient.class); 

      context.addRoutes(new HttpDynamicClient()); 
      ProducerTemplate template = context.createProducerTemplate(); 
      context.start(); 
      Thread.sleep(1000); 


      template.sendBody("direct:httpClient", "http://jsonplaceholder.typicode.com/posts/1"); 
      Thread.sleep(2000); 

      template.sendBody("direct:testMultiple", new String [] {"http://jsonplaceholder.typicode.com/posts/1" , "http://jsonplaceholder.typicode.com/posts/1"}); 


     } finally { 
      context.stop(); 
     } 
    } 

} 
+0

谢谢!!这正是我所期待的。 – tuk

1

@Darius X.的答案几乎是你所需要的。要使后端请求并行执行并将响应正文聚合到字符串列表中,您需要设置聚合策略并在拆分定义上设置并行处理标志。

@Override 
public void configure() throws Exception { 

    from("direct:testMultiple") 
      .split(body(), new FlexibleAggregationStrategy<String>() 
        .pick(Builder.body()) 
        .castAs(String.class) 
        .accumulateInCollection(ArrayList.class)) 
      .parallelProcessing() 
      // .executorService(<instance of java.util.concurrent.ExecutorService>) // optional: use custom thread pool for parallel processing 
      .to("direct:httpClient"); 

    from("direct:httpClient") 
      .log("starting httpClient route") 
      .setHeader(Exchange.HTTP_URI, simple("${body}")) 
      .setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http4.HttpMethods.GET)) 
      .to("http4://google.com") 
      .convertBodyTo(String.class) 
      .log(LoggingLevel.INFO, "Output was ${body}"); 
} 

direct:testMultiple返回的交换输出消息将包含结果数组作为正文。