浅谈 Next 开发(On the development of next)

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

  同时 Next 也是 Vert.x 及 awesome-kotlin 推荐项目。让我们来看看 Next 一些有趣的特点。

  比如直接用 Vert.x 写路由的话是下面这样的写法:

  router.route().handler(ctx -> {

  // This handler will be called for every request

  HttpServerResponse response = ctx.response();

  response.putHeader(“content-type”, “text/plain”);

  // Write to the response and end it

  response.end(“Hello World from Vert.x-Web!”);

  });

  那么当你还要操作数据库的话,那么看起来就是一个回调嵌着一个回调,很容易形成回调地狱。

  让我们看看在 Next 中如何实现一个简单的输出 Json 的路由:

  @GET(“json”)

  fun json() {

  var map = hashMapOf<String, Any>()

  map.put(“a”, 1)

  map.put(“b”, 2)

  renderJson(map)

  }

  在写法上完全不需要改变自己的习惯用传统的写法即可。甚至你还可以直接使用类似 spring boot 的参数注入的写法(结合 hibernate 的参数校验):

  fun argsController(

  @Chinese(false)

  @Parameter(“name”, defaultValue = “Peter”)

  name: String,

  @Min(18)

  @Parameter()

  age: Int ) {

  var map = hashMapOf<String, Any>()

  map[“name”] = name

  map[“age”] = age

  renderJson(map)

  }

  而且在 Cloudopt Next 中支持多种异步写法,你可以选择自己喜欢写法自由发挥:

  比如我们现在需要运行某个阻塞的代码并需要将结果传递回来,你可以用以下的方式运行。当然你也可以通过 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)

  }

  }

  }

  第四种做法是你可以在路由的方法上增加 @Blocking 注解,使其自动变为普通的路由。

  @Blocking

  @GET(“blocking”)

  fun blocking() {

  renderText(“This is Blocking!”)

  }

  比如我们利用 await 语法就可以直接使用任意的同步操作数据库 orm ,完全不用担心阻塞的问题(这里用的是 jooq):

  @GET

  suspend fun get() {

  await { promise ->

  val result = JooqManager.dsl?.selectFrom(Tables.TODO)?.fetch()?.into(Todo::class.java)

  renderJson(result )

  promise.complete()

  }

  }

  当然你把它封装好的话,看起来就是这样的:

  @GET

  suspend fun get() {

  renderJson(todoService.getTodoList())

  }

  当然还支持通过注解来设置验证器、Handler 等等,甚至还简化了 Vert.x 的 EventBus,你只需要在路由上面声明 @AfterEvent即可自动完成在 xxx 事件后执行 xxx 事件这种方式。

  @GET(“afterEvent”)

  @AfterEvent([“net.cloudopt.web.test”])

  fun afterEvent() {

  this.context.data().put(“key”,”value”)

  renderText(“AfterEvent is success!”)

  }

  你只需要在其它类上声明 @AutoEvent 并继承 EventListener 即可自动订阅这个事件。

  @AutoEvent(“net.cloudopt.web.test”)

  class TestEventListener:EventListener {

  override fun listener(message: Message<Any>) {

  print(message.body())

  }

  }

  Cloudopt Next 在很大程度上让你保留了原先的编程习惯,同时获得了 Vert.x 的强大的性能。不仅如此,Cloudopt Next 提供了大量的插件,如分布式二级缓存、jooq、redis、日志、spring支持、quartz、国际化等等 Vert.x 没有提供的功能。还兼容 Vert.x 的模块体系。也就是说你不仅可以用 Next 官方出的插件,还可以用 Vert.x 的插件以及 Vert.x 社区贡献的一系列生态。

  赶紧试试吧,使用 Koltin + Next 你将获得一个学习曲线平滑、使用简单、符合直觉且性能极高的异步服务!!!

————————

Cloudopt next is a very lightweight and modern full stack development framework based on kotlin. It supports Java and kotlin. It can handle URL parsing, data encapsulation, JSON output, etc., fundamentally reducing development time and improving development experience.

Next is also vert X and awesome kotlin recommended projects. Let’s look at some interesting features of next.

For example, use vert X writes the route in the following way:

  router.route().handler(ctx -> {

  // This handler will be called for every request

  HttpServerResponse response = ctx.response();

  response.putHeader(“content-type”, “text/plain”);

  // Write to the response and end it

  response.end(“Hello World from Vert.x-Web!”);

});

So when you have to operate the database, it seems that a callback is embedded with a callback, which is easy to form a callback hell.

Let’s see how to implement a simple route to output JSON in next:

@GET(“json”)

fun json() {

  var map = hashMapOf<String, Any>()

map. put(“a”, 1)

map. put(“b”, 2)

  renderJson(map)

}

There is no need to change your habits in writing, just use the traditional writing method. You can even directly use the parameter injection method similar to spring boot (combined with hibernate parameter verification):

  fun argsController(

  @Chinese(false)

  @Parameter(“name”, defaultValue = “Peter”)

  name: String,

@Min(18)

@Parameter()

age: Int ) {

  var map = hashMapOf<String, Any>()

map[“name”] = name

map[“age”] = age

  renderJson(map)

}

In addition, cloudopt next supports a variety of asynchronous writing methods. You can choose the writing method you like and play it freely:

For example, we now need to run a blocked code and pass the result back. You can run it in the following way. Of course, you can also use worker Worker runs blocked code. Remember to end with handler Complete passes the result.

fun test() {

  var id = worker<Int>({ handler ->

  handler.complete(1)

  }, { asyncResult ->

  //onComplete

})

}

The second way is to use the await feature of kotlin’s coprocessor, which will be more elegant. However, using the kotlin coroutine requires declaring suspend on the method. This is also our recommended asynchronous writing method.

  suspend fun test() {

  var id = await<Int> { handler ->

  handler.complete(1)

}

}

The third case is that you use await syntax where suspend syntax is not supported. You can run it in the following way:

fun test() {

global {

  var id = await<Int> { handler ->

  handler.complete(1)

}

}

}

The fourth way is that you can add @ blocking annotation to the routing method to make it automatically become an ordinary route.

  @Blocking

@GET(“blocking”)

  fun blocking() {

  renderText(“This is Blocking!”)

}

For example, by using await syntax, we can directly use any synchronous operation database ORM without worrying about blocking (jooq is used here):

@GET

  suspend fun get() {

  await { promise ->

  val result = JooqManager.dsl?.selectFrom(Tables.TODO)?.fetch()?.into(Todo::class.java)

  renderJson(result )

  promise.complete()

}

}

Of course, if you package it, it looks like this:

@GET

  suspend fun get() {

  renderJson(todoService.getTodoList())

}

Of course, it also supports setting validators, handlers, etc. through annotations, and even simplifies vert For the eventbus of X, you only need to declare @ afterevent on the route to automatically execute the XXX event after the XXX event.

  @GET(“afterEvent”)

  @AfterEvent([“net.cloudopt.web.test”])

  fun afterEvent() {

  this.context.data().put(“key”,”value”)

  renderText(“AfterEvent is success!”)

}

You only need to declare @ autoevent on other classes and inherit EventListener to automatically subscribe to this event.

  @AutoEvent(“net.cloudopt.web.test”)

  class TestEventListener:EventListener {

  override fun listener(message: Message<Any>) {

  print(message.body())

}

}

Cloudopt next allows you to retain your original programming habits to a large extent and obtain vert X’s powerful performance. Moreover, cloudopt next provides a large number of plug-ins, such as distributed L2 cache, jooq, redis, logging, spring support, quartz, internationalization, etc X does not provide functionality. Also compatible with vert X module system. In other words, you can not only use the plug-in officially released by next, but also use vert X plug-in and vert A series of ecology contributed by X community.

Try it quickly. With koltin + next, you will get an asynchronous service with smooth learning curve, easy to use, intuitive and high performance!!!