Vert.X 是一个算是新型的服务端框架,个人感觉和Spring有竞争力,并且扩展性(准确的说是自由度) 更好。 目前本人用VertX有一段时间了,并且开发了几套不同的VertX之上的扩展框架。 这些框架也是在我很多次是使用中总结的可以节省一些时间的方法。但是如果使用过Vert.X 的数据库连接的话,就会发现,这种Callback的形式实现会非常臃肿,尤其是三角形的Callback hell, 个人感觉非常难以维护。
这个Callback的问题一直没有好的解决方案,直到前几天Kotlin 1.1发布 同时也带来了测试版的Coroutine 算是Kotlin对于Callback的解决方案。 Coroutine 只使用了一个保留关键字 (suspend)来实现了对于异步函数的简单化。举个例子吧, 在一个异步请求里面需要调用Swing的主线程来更新UI
makeAsyncRequest {
// this lambda is executed when the async request completes
result, exception ->
if (exception == null) {
// display result in UI
SwingUtilities.invokeLater {
display(result)
}
} else {
// process exception
}
}
Coroutine 的版本
launch(Swing) {
try {
// suspend while asynchronously making request val result = makeRequest()
// display result in UI, here Swing context ensures that we always stay in event dispatch thread display(result)
} catch (exception: Throwable) {
// process exception }
}
是不是看起来简单了许多呢?我猜得到很多人会想问,怎么能把现有的API改成这样呢,毕竟不是所有人都用Coroutine 甚至还有很多API不是Kotlin写的呢,那么这些该怎么办呢?
我们假设有这么一个API:
fun someLongComputation(params: Params, callback: (Result) -> Unit)
我们想把它变成一个Suspend 函数只需要这样
suspend fun someLongComputation(params: Params): Result = suspendCoroutine { cont ->
someLongComputation(params) { cont.resume(it) }
}
这样就能用了,是不是很简单呢?
介绍完了,我该说我对于VertX的JDBC写的扩展了,大概就是按照上面的那样包裹的,然后把VertX的Future 弄成了直接Return,首先说的确丢失了Future.failed() 这个测试,然而会throw 一个Exception。 如果各位有什么好的建议或者更好的方法,欢迎提交Pull Request。
目前并没有完全实现所有的API包裹,下面的列表会随着我更新代码更新而更新。 大概会在这个星期左右完成所有SQLConnection里面的异步方法。(由于是用Kotlin 的Extension Function实现的,不会影响现有的函数的使用,所有不必担心兼容问题)
Github 地址 (Codetector1374/VertX-JDBC-Kotlin-Coroutine-Extension)
CI 地址(https://jenkins.codetector.cn) (里面的VertX-JDBC-Kotlin-Coroutine-Extension 项目)
欢迎各位来看。
同时也提供一个Maven 地址,会随时更新的
Maven Dependency
<dependency>
<groupId>cn.codetector.vertx</groupIp>
<artifactId>jdbc-kotlin-coroutine-extension</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
我自己的Nexus 地址,这个项目托管在上面
<repositories>
<repository>
<id>codetectorRepoRelease</id>
<name>codetectorRelease</name>
<url>http://nexus.codetector.cn/repository/codetector/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>codetectorRepoStage</id>
<name>codetectorStaging</name>
<url>http://nexus.codetector.cn/repository/codetector-staging/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>