当vert.x 工程顺利运行起来后,如果是一个web工程,通常会去写个接口测试下。官方的工程中,是一个默认的http服务,而实际使用中我们会需要一个路由,来根据不同的request信息交给不同的函数去处理,那么我们就需要一个router来干这个事。
vert.x 提供了 io.vertx.ext.web.Router 作为router的实现。
1.Router的基本使用
val server = vertx.createHttpServer()
val router = Router.router(vertx)
router.route().handler { ctx: RoutingContext ->
val response = ctx.response()
response.putHeader("content-type", "text/plain")
response.end("Hello World from Vert.x-Web!")
}
server.requestHandler(router).listen(8080){ http ->
if (http.succeeded()) {
startPromise.complete()
println("HTTP server started on port 8888")
} else {
startPromise.fail(http.cause())
}
}
2. Router处理多个handler
vert.x 支持多个handler,一个handler执行完了,到下一个继续执行。这里需要在第一个handler里讲response的 chunked设置为true
val server = vertx.createHttpServer()
val router = Router.router(vertx)
val route = router.route()
route.handler { ctx: RoutingContext ->
val response = ctx.response()
response.isChunked = true
response.write("route1\n")
ctx.vertx().setTimer(5000) { tid: Long? -> ctx.next() }
}
route.handler { ctx: RoutingContext ->
val response = ctx.response()
response.write("route2\n")
ctx.vertx().setTimer(5000) { tid: Long? -> ctx.next() }
}
route.handler { ctx: RoutingContext ->
val response = ctx.response()
response.write("route3")
// Now end the response
ctx.response().end()
}
server.requestHandler(router).listen(8888){ http ->
if (http.succeeded()) {
startPromise.complete()
println("HTTP server started on port 8888")
} else {
startPromise.fail(http.cause())
}
}
}
输出如下
3. 简单返回Json格式
在restful接口中,我们大部分时候,只需要返回一个json对象,vert.x Router提供了通过respond 来返回json
route.respond {
Future.succeededFuture(JsonObject().put("hello", "world"))
}
4.Router 对HttpMethod的支持
Router的route()函数提供了对HttpMthod的支持,可以直接作为入参
router.route(HttpMethod.GET,"/all")
同时,还提供了get(),post(),put(),delete()等方法
5.Router中传参与获取
5.1 path传参
router.get("/name/:name").respond {ctx->
val name = ctx.pathParam("name")
Future.succeededFuture(JsonObject().put("name", name))
}
5.2 query传参
router.get("/all").respond {ctx->
val name = ctx.request().getParam("name")
Future.succeededFuture(JsonArray().add(JsonObject().put("name", name)))
}
5.3 body 传参
router.post().handler(BodyHandler.create())
.respond {
val user = it.bodyAsJson.mapTo(User::class.java)
Future.succeededFuture(user)
}
这里记得要加jackson的依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.2.2</version>
</dependency>
否则会报如下错误
io.vertx.core.json.DecodeException: Mapping ms.demo.entity.User is not available without Jackson Databind on the classpath
5.4 header传参
router.delete("/:id").respond {ctx->
val token = ctx.request().getHeader("token")
println(token)
Future.succeededFuture<Void>()
}
6.嵌套路由
在使用的时候,我们一般会根据模块对接口添加公共前缀,统一处理,也就是我们常说的嵌套路由
val articleRouter = Router.router(vertx)
articleRouter.get("/all").respond {
Future.succeededFuture(JsonArray().add(JsonObject().put("name", "三国演义")))
}
val router = Router.router(vertx)
router.mountSubRouter("/articles",articleRouter)
7. 执行阻塞方法
在vert.x中,默认都是非阻塞方法,那么如果我们确实有阻塞方法的需求怎么办呢?vert.x 提供了对应的解决方案
7.1 使用blockingHandler
router.get("/blocking1").blockingHandler {
Thread.sleep(5000L)
it.response().end()
}
7.2 executeBlocking
如果不想使用blockingHandler 还可以在respond中使用executeBlocking
router.get("/blocking2").respond {
it.vertx().executeBlocking<Any> { it ->
Thread.sleep(5000L)
it.complete()
}
}
这样,就基本满足了vert.x restful 的基本使用需求了。更详细的可以看官方文档 https://vertx.io/docs/vertx-web/java/#_using_vert_x_web