Cloudopt Next 是一个非常轻量级且现代的、基于 Kotlin 编写的全栈开发框架,同时支持 Java 和 Kotlin,您可以处理 Url 的解析,数据的封装, Json 的输出等等,从根本上减少开发时间、提升开发体验。

你可以直接修改 maven 中的依赖的版本号即可:

<dependency>
    <groupId>net.cloudopt.next</groupId>
    <artifactId>cloudopt-next-web</artifactId>
    <version>3.0.0.1-RELEASE</version>
</dependency>

3.0 版本开始要求 JDK 11 及以上,Kotlin 1.5 及以上,Vert.x 4 及以上。

如果想要了解更多,可以直接前往官网或者 GitHub

核心改动

全面支持 Kotlin 协程

目前 Interceptor、 Validator、 Route 、WebSocket 都已经支持协程(suspend 和 await)。Handler 没有支持打算,主要是因为 Handler 涉及到的地方很多,基本每一步都有,理论上在 Handler 中就不应该放阻塞的、处理时间长的代码,更适合做像是日志输出等等。如果需要使用阻塞代码建议使用下面这些专门运行阻塞代码的方法。基于 Vert.x  + Kotlin 实现了支持七种协程写法:

比如我们现在需要运行某个阻塞的代码并需要将结果传递回来,你可以用以下的方式运行。当然你也可以通过 Worker.worker 运行阻塞的代码。记得在结尾通过 handler.complete 传递结果,否则会陷入一直等待。

fun test() {
    var id = worker<Int>({ handler ->
        handler.complete(1)
    }, { asyncResult ->
        //onComplete
    })
}

第二种做法是利用 kotlin 的协程的 await 特性,写起来会更为优雅。但利用 kotlin 协程需要在方法上声明 suspend。这也是我们推荐的异步写法。

suspend fun test() {
    var id = await<Int> { handler ->
        handler.complete(1)
    }
}

第三种情况是你在无法支持 suspend 语法的地方使用 await 语法。你可以使用下面的方式运行:

fun test() {
    global {
        var id = await<Int> { handler ->
            handler.complete(1)
        }
    }
}

global 语法本质上是使用 kotlin 的 GlobalScope,并自动将 NextServer 的 vertx 的协程对象配置进去。

虽然使用了 suspend 声明,根据 kotlin 的语言规范是要求所有的调用上级都需要声明。本质上 suspend 在编译后的第一个参数是传递协程对象,所以必须一级一级往上声明,让最底下的方法拿到 suspend 对象。

但是有些情况下,无法识别 suspend 语法,所以需要用其它办法将协程对象放进去。

使用 global{} 语法糖包裹后,会自动把 vertx 的协程对象往下传递。那么上级方法就不需要声明 suspend 了。

[email protected]解,使其自动变为同步的、阻塞的路由。

@Blocking
@GET("blocking")
fun blocking() {
    renderText("This is Blocking!")
}

第五种情况是,如果你要运行超过 10s 以上时间的代码,请不要使用上面的任意方法,建议使用 then 语法。

then 的语法糖会将包裹的代码放入上下文事件的队列中,会在上下文中所有的排队都处理完后才会被异步执行。

then{
    println(1)
}

第六种情况是在 await 中直接返回。

val text = await {
    return@await "success"
}

第七种情况是在不方便声明 suspend 的时候使用 async 方法体。

private fun asyncFunction(): String = async {
    return@async await {
        return@await "success"
    }
}

全新的插件

插件全部都使用了协程重新设计,重构了 Redis、Cache 插件。新增了 ClickHouse、GRPC、Health、Polyglot 插件。

新版的 Redis 插件用 Lettuce 替换了 Jedis,同时支持使用 Next 独有的协程语法配合 Lettuce 的操作方法来操作 Redis。

var value = await<String>{handler->
    handler.complete(RedisManager.sync().get("key"))
}

新版的 Cache 插件自带分布式的二级缓存。基于 caffeine 和 Redis 实现了高效的二级分布式缓存,同时与 Redis 插件复用,还支持使用 @Cacheable 自动让路由设置缓存。

@GET("cacheable/:id")
@Cacheable("testRegion", key = "@{url}-@{id}", keyGenerator = DefaultKeyGenerator::class, l2 = true)
fun cacheable() {
    renderJson(json("name" to "cacheable"))
}

gRPC 插件为 Next 带来了对 gRPC 的支持,只要在启动时加载 gRPC 插件,即可直接启动 gRPC 的服务监听,且与 Http 服务共用所有的插件。

fun main() {
    NextServer.addPlugin(GrpcPlugin())
    NextServer.run()
}

Health 插件是一个帮助做健康检查的插件,同时支持自定义健康检查、检查回调、Json 报告。

fun main() {
    HealthChecksManager.register("disk", DiskSpaceHealthIndicator())
    HealthChecksManager.register("jvm", JvmHealthIndicator())
    HealthChecksManager.register("system", SystemIndicator())
    HealthChecksManager.registerHook("logger", LoggerHook())
    NextServer.addPlugin(HealthChecksPlugin())
    NextServer.run()
}

Polyglot 插件为 Next 提供了对 GraalVM 的支持,在使用 GraalVM 的情况下,可以直接在 Kotlin 中运行 Python、JavaScript、Ruby、R。

python { 
   "print('Hello Python!')"
}

方法级别的拦截器

在 3.0.0.0 正式版后支持全新的 Before 和 After 的 RouteHandler 机制,任意注解只要在里面声明 @Before  或者 @After  并且声明了对应的实现处理类,那么路由会自动根据是 Before 还是 After 实现类似 AOP 的拦截机制。

更多地方支持了 DSL

我们有更多的地方提供了 Kotlin DSL 的相关支持,如:

json(
    "a" to "1",
    "b" to json(
        "c" to "2"
    ),
    "c" to jsonArray(
        json(
            "d" to "3"
        )
    ),
    "student" to Student(name = "next", sex = 1)
)

此外还有将近 30+ 个特性更新,120 + 次提交。

获取帮助和支持

  • 请仔细检查 参考文档,查看具体的代码案例或者是常见问题。
  • 如果您在升级版本以后遇到问题,可以查看 Wiki 中的升级说明。
  • 请发送邮件到 [email protected]
  • 请在 GitHub 发送 Issue 提交您的问题,我们将尽快为您解答。
  • 如果您在中国,还可以加入交流 QQ 群:557692142。

项目地址

我们其它有趣的研究

Cloudopt AdBlocker

Cloudopt AdBlocker 是基于 AdguardBrowserExtension 以及 Cloudopt 自主研发的云信誉评估技术的浏览器扩展,实时保护您的安全、防止追迹、恶意域名,过滤横幅广告、弹窗广告等等。

Baize

白泽是直接运行在浏览器上且基于机器学习的隐私保护引擎,能够有效的阻挡跟踪脚本、恶意广告脚本。使用 JavaScript 开发,可以运行在 Node.js、浏览器环境中。

pyencrypt-plus

这是一个具备多种常见的加密算法且使用起来极其方便的 python 加密库。全部加密算法都继承自统一的抽象接口,做到使用起来无需关心技术细节、五分钟上手。