创建支持 Kotlin 协程的 Vert.x 服务代理

Vert.x 官方的 Service Proxies 文档写得很糟糕。本文提供一个方法,可用于创建支持 Kotlin 协程的 Vert.x 服务代理。

服务接口和实现

新建 TestService.ktTestServiceImpl.ktpackage-info.java 三个文件:

kotlin// TestService.kt
package io.vertx.samples.services

import io.vertx.codegen.annotations.ProxyGen
import io.vertx.codegen.annotations.VertxGen
import io.vertx.core.AsyncResult
import io.vertx.core.Handler

@ProxyGen
@VertxGen
interface TestService {
    fun test(text: String, handler: Handler<AsyncResult<String>>)
}
kotlin// TestServiceImpl.kt
package io.vertx.samples.services

import io.vertx.core.AsyncResult
import io.vertx.core.Future
import io.vertx.core.Handler

class TestServiceImpl : TestService {
    override fun test(text: String, handler: Handler<AsyncResult<String>>) {
        handler.handle(Future.succeededFuture("echo: $text"))
    }
}
java// package-info.java
@ModuleGen(groupPackage = "io.vertx.samples", name = "services")
package io.vertx.samples.services;

import io.vertx.codegen.annotations.ModuleGen;

构建脚本

此处使用 Gradle 作为项目构建工具、kotlin 作为 DSL。修改 build.gradle.kts文件:

kotlinplugins {
    val kotlinVersion = "1.3.72"
    // 添加 kapt 插件
    kotlin("kapt") version kotlinVersion
    ... ...
}

val vertxVersion = "4.0.0.CR2"

dependencies {
    // 添加依赖
    implementation("io.vertx:vertx-service-proxy:$vertxVersion")
    implementation("io.vertx:vertx-codegen:$vertxVersion")
    implementation("io.vertx:vertx-lang-kotlin:$vertxVersion")
    implementation("io.vertx:vertx-lang-kotlin-gen:$vertxVersion")
    implementation("io.vertx:vertx-lang-kotlin-coroutines:$vertxVersion")
    kapt("io.vertx:vertx-codegen:$vertxVersion:processor")
    compileOnly("io.vertx:vertx-codegen:$vertxVersion")
    ... ...
}

运行 gradle build 后,分别会在 build\generated\source\kapt\main 目录下生成 io.vertx.samples.services.TestServiceVertxEBProxyio.vertx.samples.services.TestServiceVertxProxyHandler 两个 Java 类,以及 build\generated\source\kaptKotlin\main 目录下生成 io.vertx.samples.kotlin.services.TestService 的 Kotlin 类扩展方法。

注册服务

kotlinimport io.vertx.serviceproxy.ServiceBinder

val service = TestServiceImpl()
val binder = ServiceBinder(vertx)
val consumer = binder.setAddress("service.address").register(TestService::class.java, service)

调用服务

kotlinimport io.vertx.serviceproxy.ServiceProxyBuilder

val builder = ServiceProxyBuilder(vertx).setAddress("service.address")
val service = builder.build(TestService::class.java)
val result = service.testAwait("Hello")

该方法可以生成支持协程调用的代理类,然而并不支持服务接口使用 suspend 关键字。