# vertx-kotlin-rpc **Repository Path**: windoze/vertx-kotlin-rpc ## Basic Information - **Project Name**: vertx-kotlin-rpc - **Description**: 用Kotlin实现的极简的Vertx RPC框架,同时支持Java和Kotlin。 - **Primary Language**: Kotlin - **License**: WTFPL - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 30 - **Forks**: 7 - **Created**: 2019-01-27 - **Last Updated**: 2024-02-22 ## Categories & Tags **Categories**: rpc **Tags**: None ## README Vertx Kotlin RPC over EventBus ============================== [![CircleCI](https://circleci.com/gh/windoze/vertx-kotlin-rpc.svg?style=svg)](https://circleci.com/gh/windoze/vertx-kotlin-rpc) [![Download](https://api.bintray.com/packages/windoze/maven/vertx-kotlin-rpc/images/download.svg) ](https://bintray.com/windoze/maven/vertx-kotlin-rpc/_latestVersion) 极简的Vertx/Kotlin RPC框架。 开始 ---- Maven包已发布到jCenter,请先按照[说明](https://bintray.com/beta/#/bintray/jcenter)配置maven或gradle的设置。 Maven: ```xml codes.unwritten vertx-kotlin-rpc 0.6 pom ``` Gradle: ```Groovy compile 'codes.unwritten:vertx-kotlin-rpc:0.6' ```
在Kotlin中创建RPC service ----------------------- ```kotlin import codes.unwritten.vertx.kotlin.rpc.RpcServerVerticle //... // 只要方法的签名匹配,服务可以不用实现用于定义接口的interface class HelloSvcImpl { // 方法可以是suspend,也可以不是 fun hello(name: String): String = "Hello, $name!" } // ... vertx.deployVerticle(RpcServerVerticle("test-channel") .register("hello", HelloSvcImpl())) ``` 在Kotlin中调用RPC service --------------------- ```kotlin import codes.unwritten.vertx.kotlin.rpc.getServiceProxy // ... // 服务接口定义 interface HelloSvc { // 成员函数必须是suspend,否则在调用的时候会抛出异常 suspend fun hello(world: String): String } // ... // 创建服务的Proxy对象 val svc: HelloSvc = getServiceProxy(vertx, "test-channel", "hello") // 调用RPC服务 assertEqual("Hello, world!", svc.hello("world")) ``` 在Kotlin中创建HTTP RPC service ---------------------------- ```kotlin import io.vertx.core.Vertx import io.vertx.ext.web.Router import io.vertx.ext.web.handler.BodyHandler import io.vertx.kotlin.coroutines.CoroutineVerticle import codes.unwritten.vertx.kotlin.rpc.HttpRpcHandler // ... class SomeVerticle: CoroutineVerticle() { override suspend fun start() { // ... val router = Router.router(vertx) // 必须打开BodyHandler router.route().handler(BodyHandler.create()) // 只支持POST method router.post("/some-path").handler(HttpRpcHandler().register("hello", object { fun hello(name: String): String = "Hello, $name!" })) // 启动HTTP server // ... } } ``` 在Kotlin中调用HTTP RPC service -------------------------- ```kotlin import codes.unwritten.vertx.kotlin.rpc.getHttpServiceProxy interface HelloSvc { // 成员函数必须是suspend,否则在调用的时候会抛出异常 suspend fun hello(name: String): String } // ... // 用指定的URL创建服务的Proxy对象 val svc = getHttpServiceProxy(vertx, "http://127.0.0.1:8080/some-path", "hello") // 调用HTTP RPC服务 assertEqual("Hello, world!", svc.hello("world")) ``` 在Kotlin中调用JSON RPC service -------------------------- ```kotlin import codes.unwritten.vertx.kotlin.rpc.HttpRequest import codes.unwritten.vertx.kotlin.rpc.JsonRpcException import codes.unwritten.vertx.kotlin.rpc.QueryParam import codes.unwritten.vertx.kotlin.rpc.getHttpJsonRpcServiceProxy interface DemoSvc { // 成员函数必须是suspend,否则在调用的时候会抛出异常 // HttpRequest annotation可以用了定制映射 // 缺省的方法是POST,缺省路径是方法名 @HttpRequest(method = HttpMethod.GET, path = "comments") suspend fun getComments(postId: Int): List } // ... // 用指定的URL创建服务的Proxy对象 val svc = getHttpJsonRpcServiceProxy(vertx, "https://postman-echo.com/") // 调用JSON RPC服务 context.assertTrue(svc.getComments(1).isNotEmpty()) ``` Query Param示例: ``` interface DemoSvc { @HttpRequest(method = HttpMethod.POST, path="somepath") // QueryParam annotation表明这个参数是query parameter而不是body的一部分,也可以指定参数名称 // foo3将会作为body的一部分被发往server suspend fun someMethod(@QueryParam foo1: String, @QueryParam("foo2") arg2: String, foo3: String): SomeResponse } ``` 在Java中创建RPC service ---------------------- ```java import codes.unwritten.vertx.kotlin.rpc.RpcServerVerticle; // ... // 实现类不返回Future,直接返回T public class HelloSvcImpl { public String hello(String name) { return "Hello, " + name + "!"; } } // ... vertx.deployVerticle((new RpcServerVerticle("test-channel")) .register("hello", new HelloSvcImpl())); ``` 在Java中调用RPC service ------------------------------- Java没有suspend函数,所以服务接口中的每个方法必须返回`Future`而不是`T`。 ```Java import io.vertx.core.Future; import static codes.unwritten.vertx.kotlin.rpc.ServiceProxyFactory.getAsyncServiceProxy; // ... // 方法必须返回Future而不是T interface AsyncHelloSvc { Future hello(String world); } // ... AsyncHelloSvc svc = getAsyncServiceProxy(vertx, "test-channel", "hello", AsyncHelloSvc.class); svc.hello("world").setHandler(ar -> { if (ar.succeeded()) { assertEquals("Hello, world!", ar.result()); } else { // Error handling } }); ``` 在Java中创建HTTP RPC service --------------------------- (略) 在Java中调用HTTP RPC service --------------------------- Java没有suspend函数,所以服务接口中的每个方法必须返回`Future`而不是`T`。 ```Java import io.vertx.core.Future; import static codes.unwritten.vertx.kotlin.rpc.AsyncServiceProxyFactory.getAsyncHttpServiceProxy; // ... // 方法必须返回Future而不是T interface AsyncHelloSvc { Future hello(String world); } // ... AsyncHelloSvc svc = getAsyncHttpServiceProxy(vertx, "http://127.0.0.1:8080/some-path", "hello", AsyncHelloSvc.class); svc.hello("world").setHandler(ar -> { if (ar.succeeded()) { assertEquals("Hello, world!", ar.result()); } else { // Error handling } }); ``` Notes ----- * JSON RPC使用[Jackson](https://github.com/FasterXML/jackson)进行序列化和反序列化。 * 所有其它的参数和返回值都由[Kryo](https://github.com/EsotericSoftware/kryo)进行序列化和反序列化,请参阅文档以了解更多的细节。 * Java反射API不能获取方法的参数名称,而这是JSON RPC必须的功能,所以JSON RPC目前无法支持Java。如果你有什么好主意请告诉我。 TODO ---- * 支持方法重载 * RPC调用跟踪 * JSON RPC支持路径参数