如何在Camel中Post一个请求?

Apache Camel是一个强大的开源集成框架。它提供了一套成熟的组件来与各种协议和系统进行交互,包括HTTP。

在本文中,我们将学习如何使用 Apache Camel 向外部服务器发出 POST 请求。我们首先定义一个使用 JSON 字符串和 POJO 发送 POST 请求的路由。

此外,我们还了解了如何使用 HTTP 组件与外部 API 进行通信。最后,我们编写了一个单元测试来验证我们的路由行为。

在本教程中,我们将探索 Apache Camel HTTP 组件并演示如何向JSONPlaceholder(一个用于测试和原型设计的免费虚假 API)发起 POST 请求。

Apache Camel HTTP 组件 Apache Camel HTTP 组件提供与外部 Web 服务器通信的功能。它支持各种 HTTP 方法,包括 GET、POST、PUT、DELETE 等。

默认情况下,HTTP 组件使用端口 80(用于 HTTP)和端口 443(用于 HTTPS)。以下是 HTTP 组件 URI 的一般语法:

http://hostname[:port][/resourceUri][?options]

该组件必须以“ http ”或“ https ”方案开头,后跟主机名、可选端口、资源路径和查询参数。

我们可以使用URI中的httpMethod选项设置 HTTP 方法:

https://jsonplaceholder.typicode.com/posts?httpMethod=POST

另外,我们可以在消息头中设置HTTP方法:

setHeader(Exchange.HTTP_METHOD, constant("POST"))

设置 HTTP 方法对于成功发起请求至关重要。

项目设置 首先,让我们将camel-core和camel-test-jnit5依赖项添加到pom.xml:

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-core</artifactId>
    <version>4.6.0</version>
</dependency>
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-test-junit5</artifactId>
    <version>4.6.0</version>
</dependency>
camel -core依赖项提供了系统集成的核心类。其中一个重要类是用于创建路由的RouteBuilder。camel-test-junit5 提供了使用JUnit 5测试 Camel 路由的支持。

接下来,让我们将camel-jackson和camel-http依赖项添加到pom.xml中:

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-jackson</artifactId>
    <version>4.6.0</version>
</dependency>
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-http</artifactId>
    <version>4.6.0</version>
</dependency>
camel -http 依赖项为 HTTP 组件与外部服务器通信提供支持。此外,我们添加了camel-jackson依赖项,以便使用 Jackson 进行JSON序列化和反序列化。

然后,让我们为对“ https://jsonplaceholder.typicode.com/post ”的 POST 请求创建一个示例JSON负载:

{
  "userId": 1,
  "title": "Java 21",
  "body": "Virtual Thread",
}
这里,有效负载包含userId、title和body。我们期望端点在成功创建新帖子时返回 HTTP 状态代码 201。

发送 Post 请求 首先,让我们创建一个名为PostRequestRoute 的类,它扩展了RouteBuilder类:

public class PostRequestRoute extends RouteBuilder { 
}
RouteBuilder类允许我们重写configure()方法来创建路线。

使用 JSON 字符串发送 Post 请求 让我们定义一个向我们的虚拟服务器发送 POST 请求的路由:

from("direct:post").process(exchange -> exchange.getIn()
  .setBody("{\"title\":\"Java 21\",\"body\":\"Virtual Thread\",\"userId\":\ŕ\"}"))
  .setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
  .to("https://jsonplaceholder.typicode.com/posts?httpMethod=POST")
  .to("mock:post");
在这里,我们定义一个路由并将有效负载设置为 JSON 字符串。setBody ()  body方法接受 JSON 字符串作为参数。此外,我们使用httpMethod选项将 HTTP 方法设置为 POST。

然后,我们将请求发送到 JSONPlacehoder API。最后,我们将响应转发到模拟端点。

使用 POJO 类发送 Post 请求 但是,定义 JSON 字符串可能容易出错。为了实现更类型安全的方法,我们定义一个名为 Post 的POJO类:

public class Post {
    private int userId;
    private String title;
    private String body;
    // standard constructor, getters, setters
}
接下来,让我们修改路由以使用 POJO 类:

from("direct:start").process(exchange -> exchange.getIn()
  .setBody(new Post(1, "Java 21", "Virtual Thread"))).marshal().json(JsonLibrary.Jackson)
  .setHeader(Exchange.HTTP_METHOD, constant("POST"))
  .setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
  .to("https://jsonplaceholder.typicode.com/posts")
  .process(exchange -> log.info("The HTTP response code is: {}", exchange.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE)))
  .process(exchange -> log.info("The response body is: {}", exchange.getIn().getBody(String.class)))
  .to("mock:result");
在这里,我们从名为start的直接端点开始。然后,我们创建一个Post实例并将其设置为请求主体。此外,我们使用Jackson将 POJO 编组为 JSON。

接下来,我们将请求发送到虚假 API 并记录响应代码和正文。最后,我们将响应转发到模拟端点以进行测试。

测试路线 让我们编写一个测试来验证我们的路由行为。首先,让我们创建一个扩展CamelTestSupport类的测试类:

class PostRequestRouteUnitTest extends CamelTestSupport {
}
然后,让我们创建一个模拟端点和生产者模板:

@EndpointInject("mock:result")
protected MockEndpoint resultEndpoint;
@Produce("direct:start")
protected ProducerTemplate template;
接下来,让我们重写createRouteBuilder()方法以使用PostRequesteRoute:

@Override
protected RouteBuilder createRouteBuilder() {
    return new PostRequestRoute();
}
最后我们来写一个测试方法:

@Test
void whenMakingAPostRequestToDummyServer_thenAscertainTheMockEndpointReceiveOneMessage() throws Exception {
    resultEndpoint.expectedMessageCount(1);
    resultEndpoint.message(0).header(Exchange.HTTP_RESPONSE_CODE)
      .isEqualTo(201);
    resultEndpoint.message(0).body()
      .isNotNull();
    template.sendBody(new Post(1, "Java 21", "Virtual Thread"));
    resultEndpoint.assertIsSatisfied();
}
在上面的代码中,我们定义了对模拟端点的期望,并使用template.sendBody()方法发送请求。最后,我们确定模拟端点的期望得到满足。