Web 与 HTTP 服务
你当前正在浏览历史版本 Vert.x 4.5.35 的文档。 访问本页面的 最新版本。

Vert.x Web API Service

Preview

Vert.x Web API Service 帮助你通过 Vert.x EventBus(事件总线)以 RPC 风格透明解耦并处理 HTTP 请求。

EventBus 提供了极其强大的服务间解耦能力,包括集群内跨进程/跨机器的动态负载均衡与流量分发。更多细节欢迎查阅 Event Bus 官方文档。

该模块基于 Vert.x Service Proxy 的设计思想,允许你创建 Web API Service 服务消费者,并通过内置 Handler 自动将前端 HTTP 请求打包代理至后端对应的服务接口。

使用 Vert.x API Service

在工程构建文件中添加依赖:

  • Maven(在 pom.xml 中):

<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-codegen</artifactId>
  <version>5.0.12</version>
  <classifier>processor</classifier>
</dependency>
<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-web-api-service</artifactId>
  <version>5.0.12</version>
</dependency>
  • Gradle(在 build.gradle 文件中):

dependencies {
  annotationProcessor 'io.vertx:vertx-codegen:5.0.12:processor'
  annotationProcessor 'io.vertx:vertx-web-api-service:5.0.12'
  compile 'io.vertx:vertx-web-api-service:5.0.12'
}

引入 vertx-codegen 是为了在编译期通过注解处理器(APT)自动生成代理接口的胶水代码。若仅使用 RouteToEBServiceHandler,则无需引入生成器。

若需要在不同多语言环境间调用该服务接口,需引入对应的语言扩展包(如 Groovy 需引入 vertx-lang-groovy)。

将 HTTP 请求透明代理至 Web API Service

通过 RouteToEBServiceHandler,你可以将 HTTP 请求直接桥接至 EventBus。 该 Handler 会自动从 RoutingContext 中提取上下文数据封装为 ServiceRequest,并通过 EventBus 请求后端,最终将返回的 ServiceResponse 自动回写给客户端:

router
  .get("/hello")
  .handler(validationHandler)
  .handler(
    RouteToEBServiceHandler
      .build(eventBus, "greeters.myapplication", "hello")
  );

你还可以配置专用的 DeliveryOptions(如自定义 RPC 超时时间):

router
  .get("/hello")
  .handler(validationHandler)
  .handler(
    RouteToEBServiceHandler
      .build(eventBus, "greeters.myapplication", "hello",
        new DeliveryOptions().setSendTimeout(1000))
  );
在挂载 RouteToEBServiceHandler 之前,必须 先行挂载负责提取并校验请求参数的 ValidationHandler,否则无法自动向下游服务传递请求参数。

定义 Web API Service 接口规范

在深入之前,推荐先阅读 Service Proxy 官方文档。

假设我们在 Router 中声明了以下两条路由:

router.get("/api/transactions")
  .handler(
    ValidationHandlerBuilder.create(repository)
      .queryParameter(optionalParam("from", stringSchema()))
      .queryParameter(optionalParam("to", stringSchema()))
      .build()
  ).handler(
    RouteToEBServiceHandler.build(eventBus, "transactions.myapplication",
      "getTransactionsList")
  );
router.post("/api/transactions")
  .handler(
    ValidationHandlerBuilder.create(repository)
      .body(json(objectSchema()))
      .build()
  ).handler(
    RouteToEBServiceHandler.build(eventBus, "transactions.myapplication",
      "putTransaction")
  );

GET /api/transactions 接收两个可选查询参数 from 与 to;POST /api/transactions 接收 JSON 请求体。

接下来我们定义处理这两个接口的 Java 业务接口 TransactionService。 接口中的方法名称需与构建 RouteToEBServiceHandler 时指定的 action 严格对应。参数签名需遵循以下规范:

  • 最后一个参数类型必须为 Handler<AsyncResult<ServiceResponse>>(异步结果回调)

  • 倒数第二个参数类型必须为 ServiceRequest(请求上下文元数据)

  • 从第一个到倒数第三个参数,系统会自动从 RequestParameters 中按名称自动提取并做类型转换,但参数类型需遵循 Service Proxy 的规范约束

方法参数名即为提取参数时的 Key;特殊的参数名 body 专门用于提取 HTTP 请求体:

@WebApiServiceGen
interface TransactionService {
  void getTransactionsList(String from, String to, ServiceRequest context, Handler<AsyncResult<ServiceResponse>> resultHandler);
  void putTransaction(JsonObject body, ServiceRequest context, Handler<AsyncResult<ServiceResponse>> resultHandler);
}

当客户端访问 TransactionService#getTransactionsList 时,生成的代理层会自动从 ServiceRequest 中提取 from 与 to;在 putTransaction 中则自动提取 JSON 请求体。

若定义了符合规范的 Vert.x DataObject(如 Transaction),系统还支持直接映射为强类型对象:

void putTransaction(Transaction body, ServiceRequest context, Handler<AsyncResult<ServiceResponse>> resultHandler);

实现 Web API Service 业务逻辑

实现接口时,通过回调传入 ServiceResponse 即可构建响应。系统提供了诸如 completedWithJson 或 completedWithPlainText 等快捷工厂方法:

resultHandler.handle(
  Future.succeededFuture(
    ServiceResponse.completedWithJson(new JsonArray())
  )
);

发生业务异常时:

resultHandler.handle(
  Future.failedFuture(
    new HttpException(555, "处理发生未知异常")
  )
);

ServiceRequest 数据对象

ServiceRequest 是 RoutingContext 的轻量级可序列化版本,跨 EventBus 传递:

  • getHeaders():获取原始请求头

  • getParams():包含所有解析合规的参数集合

  • getUser():包含登录用户的 principal,未登录时为 null

  • getExtra():支持配置自定义透传附加字段

ServiceResponse 数据对象

封装了响应头、HTTP 状态码及响应负载内容。

暴露并注册你的 Web API Service

将实现类注册到 EventBus 指定地址上:

TransactionService transactionService = new TransactionServiceImpl();

// 在 EventBus 上绑定服务
ServiceBinder transactionServiceBinder = new ServiceBinder(vertx);
transactionServiceBinder
  .setAddress("transactions.myapplication")
  .register(TransactionService.class, transactionService);

与 OpenAPI 深度集成

Vert.x Web API Service 提供了 OpenAPIRouterHandler,可直接绑定至 OpenAPIRoute,自动将符合 OpenAPI 规范的外部请求流转至后端 RPC 服务代理:

OpenAPIContract contract = getContract();
ResponseValidator responseValidator = ResponseValidator.create(vertx, contract);

OpenAPIRoute route = routerBuilder.getRoute("getPets");
OpenAPIRouterHandler handler = OpenAPIRouterHandler.create(vertx,
  route.getOperation(), responseValidator);

route.addHandler(handler);

在 OpenAPI 规范文件中,只需在对应接口中配置 x-vertx-event-bus 扩展字段,指明目标 EventBus 地址即可完成无缝联动:

paths:
  /pets:
    get:
      operationId: listPets
      x-vertx-event-bus:
        address: myEventbusAddress
        method: getPetById