共计 7137 个字符,预计需要花费 18 分钟才能阅读完成。
Vert .x
什么是Vert .x
?
Vert.x 框架基于事件和异步,依靠于全异步 Java 服务器 Netty,并扩大了很多其余个性,以其轻量、高性能、反对多语言开发
Hello world
创立一个简略的我的项目 https://start.vertx.io/ 无需增加任何依赖
public class MainVerticle extends AbstractVerticle {
@Override
public void start(Promise<Void> startPromise) throws Exception {vertx.createHttpServer().requestHandler(req -> {req.response()
.putHeader("content-type", "text/plain")
.end("Hello from Vert.x!");
}).listen(8888, http -> {if (http.succeeded()) {startPromise.complete();
System.out.println("HTTP server started on port 8888");
} else {startPromise.fail(http.cause());
}
});
}
这个代码第一眼看上去就很简单,然而其实仔细分析一下,会感觉其实很好了解
大抵就是 Vert.x
创立了一个 Http
的服务, 并增加申请头和响应的内容,监听 8888
的端口,当服务创立胜利时输入HTTP server started on port 8888
Run
上面两个命令很重要切记
打包
$ mvn package
运行
$ mvn exec:java
HTTP server started on port 8888
一月 28, 2021 11:14:37 下午 io.vertx.core.impl.launcher.commands.VertxIsolatedDeployer
信息: Succeeded in deploying verticle
拜访
$ curl http://127.0.0.1:8888/
Hello from Vert.x!
web
我的项目
增加 Vert.x Web
依赖
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
</dependency>
public class MainVerticle extends AbstractVerticle {
@Override
public void start(Promise<Void> startPromise) throws Exception {
// 创立一个路由
Router router = Router.router(vertx);
// 在每个门路和 HTTP 办法中为所有传入申请装置处理程序
router.route().handler(context -> {
// 获取申请的地址
String address = context.request().connection().remoteAddress().toString();
// Get the query parameter "name"
MultiMap queryParams = context.queryParams();
String name = queryParams.contains("name") ? queryParams.get("name") : "unknown";
// Write a json response
context.json(new JsonObject()
.put("name", name)
.put("address", address)
.put("message", "Hello" + name + "connected from" + address)
);
});
// Create the HTTP server
vertx.createHttpServer()
// Handle every request using the router(应用路由器解决每个申请).requestHandler(router)
// Start listening
.listen(8888)
// Print the port
.onSuccess(server ->
System.out.println("HTTP server started on port" + server.actualPort()
)
);
}
}
拜访
$ curl http://127.0.0.1:8888/
{"name":"unknown","address":"127.0.0.1:3402","message":"Hello unknown connected from 127.0.0.1:3402"}
$ curl http://127.0.0.1:8888?name=shaojie
{"name":"shaojie","address":"127.0.0.1:3605","message":"Hello shaojie connected from 127.0.0.1:3605"}
Vert.x-Web 基本概念
Router
是 Vert.x-Web 的外围概念之一。它是放弃零个或多个的对象 Routes
。
路由器接管一个 HTTP 申请,并找到该申请的第一个匹配路由,而后将申请传递到该路由。
路由能够具备与之关联的 处理程序 ,该 处理程序 而后接管申请。而后 , 您能够对申请进行解决,而后完结申请或将其传递给下一个匹配的处理程序。
创立一个简略的路由:
HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
router.route().handler(ctx -> {HttpServerResponse response = ctx.response();
response.putHeader("content-type", "text/plain");
response.end("Hello World from Vert.x-Web!");
});
server.requestHandler(router).listen(8080);
解决申请并调用下一个处理程序
当 Vert.x-Web 决定将申请路由到匹配的路由时,它将在的实例中传递该路由的处理程序RoutingContext
。路由能够具备不同的处理程序,您能够应用 handler
如果您未在处理程序中完结响应,则应进行调用,next
以便其余匹配的路由能够解决申请(如果有)。
Route route = router.route("/some/path/");
route.handler(ctx -> {HttpServerResponse response = ctx.response();
// 启用分块响应,因为咱们将在执行其余处理程序时增加数据。仅一次且仅当多个处理程序进行输入时才须要这样做
response.setChunked(true);
response.write("route1\n");
// 提早 5 秒后呼叫下一条匹配路线
ctx.vertx().setTimer(5000, tid -> ctx.next());
});
route.handler(ctx -> {HttpServerResponse response = ctx.response();
response.write("route2\n");
// 提早 5 秒后呼叫下一条匹配路线
ctx.vertx().setTimer(5000, tid -> ctx.next());
});
route.handler(ctx -> {HttpServerResponse response = ctx.response();
response.write("route3");
// Now end the response
ctx.response().end();
});
$ curl http://127.0.0.1:8080/some/path/
route1
route2
route3
在下面的示例 route1
中,将响应写入响应,而后在 5 秒钟后将 route2
其写入响应,而后在 5 秒钟后将 route3
其写入响应,并完结响应。(留神,所有这些都在没有任何线程阻塞的状况下产生。)
简略的回应
处理程序十分弱小,因为它们容许您构建非常复杂的应用程序。对于简略的响应,例如,间接从 vert.x API 返回异步响应,路由器包含处理程序的快捷方式,以确保:
- 响应以 JSON 返回。
- 如果解决处理程序时产生谬误,则返回正确的谬误。
- 如果序列化对 JSON 的响应时出错,则返回正确的谬误。
router
.get("/some/path")
// 此处理程序将确保将响应序列化为 json,并将内容类型设置为“application/json”.respond(ctx -> Future.succeededFuture(new JsonObject().put("hello", "world")));
router
.get("/some/path")
// 这个处理程序将确保 Pojo 被序列化为 json 内容类型设置为“application/json”.respond(ctx -> Future.succeededFuture(new Pojo()));
$ curl http://127.0.0.1:8080/some/path/
{"hello":"world"}
然而,如果提供的函数调用 write
或,您也能够将其用于非 JSON 响应end
:
router
.get("/some/path")
.respond(
ctx -> ctx
.response()
.putHeader("Content-Type", "text/plain")
.end("hello world!"));
router
.get("/some/path")
// 在这种状况下,处理程序确保连贯曾经完结
.respond(
ctx -> ctx
.response()
.setChunked(true)
.write("Write some text..."));
$ curl http://127.0.0.1:8080/some/path/
hello world!
$ curl http://127.0.0.1:8080/some/path/
Write some text...
路由
按确切门路路由
Route route = router.route().path("/some/path/");
route.handler(ctx -> {
// 此处理程序将被以下申请门路调用:
// `/some/path/`
// `/some/path//`
// but not:
// `/some/path` 门路的完结斜杠使其严格
// `/some/path/subdir`
HttpServerResponse response = ctx.response();
response.putHeader("content-type", "text/plain");
response.end("/some/path/");
});
// 不以斜杠完结的门路不严格 前面的斜杠是可选的 它们能够任意匹配
Route route2 = router.route().path("/some/path");
route2.handler(ctx -> {
// 此处理程序将被以下申请门路调用:
// `/some/path`
// `/some/path/`
// `/some/path//`
// but not:
// `/some/path/subdir`
HttpServerResponse response = ctx.response();
response.putHeader("content-type", "text/plain");
response.end("/some/path");
});
通过以某些内容结尾的门路进行路由
Route route = router.route().path("/some/path/*");
route.handler(ctx -> {
// 此处理程序将被以下申请门路调用:
// `/some/path/`, e.g.
// `/some/path/`
// `/some/path/subdir`
// `/some/path/subdir/blah.html`
// but not:
// `/some/path` 该门路是严格的,因为它以斜杠完结
// `/some/bath`
HttpServerResponse response = ctx.response();
response.putHeader("content-type", "text/plain");
response.end("/some/path/*");
});
通过 HTTP 办法路由
Route route = router.route(HttpMethod.POST, "/some/path/");
route.handler(ctx -> {
// 对于以 /some/path/ 结尾的 URI 门路的任何 POST 申请,都会调用此处理程序
HttpServerResponse response = ctx.response();
response.putHeader("content-type", "text/plain");
response.end("method--/some/path/");
});
间接调用
get
、post
、put
和 delete
等以 HTTP 办法名称命名
router
.get("/some/path")
.respond(
ctx -> ctx
.response()
.putHeader("Content-Type", "text/plain")
.end("hello world!"));
如果要指定一个路由将匹配多个 HTTP 办法,则能够method
屡次调用:
Route route = router.route().method(HttpMethod.POST).method(HttpMethod.PUT);
route.handler(ctx -> {});
如果要创立须要自定义 HTTP 动词的应用程序(例如 WebDav
服务器),则能够指定自定义动词
Route route = router.route()
.method(HttpMethod.valueOf("MKCOL"))
.handler(ctx -> {// 任何 MKCOL 申请都将调用此处理程序});
路线程序
参考 解决申请并调用下一个处理程序
如果要笼罩路由的默认程序,能够应用order
,指定一个整数值。
路由在创立时被调配一个与增加到路由器的程序绝对应的程序,第一个路由编号0
,第二个路由编号1
,依此类推。
通过指定路线的程序,您能够笼罩默认程序。订单也能够是正数,例如,如果您要确保在路线编号之前评估一条路线0
。
router
.route("/some/path/")
.order(1)
.handler(ctx -> {HttpServerResponse response = ctx.response();
response.write("route1\n");
// Now call the next matching route
ctx.next();});
router
.route("/some/path/")
.order(0)
.handler(ctx -> {HttpServerResponse response = ctx.response();
// 启用分块响应,因为咱们将在执行其余处理程序时增加数据。// 仅一次且仅当多个处理程序进行输入时才须要这样做。response.setChunked(true);
response.write("route2\n");
// Now call the next matching route
ctx.next();});
router
.route("/some/path/")
.order(2)
.handler(ctx -> {HttpServerResponse response = ctx.response();
response.write("route3");
// Now end the response
ctx.response().end();
});
$ curl http://127.0.0.1:8080/some/path/
route2
route1
route3
对于路由得货色太多,前面独自整顿一期,独自钻研一下,刚开始学习的话,还是先会用比拟好
捕捉门路参数
router
.route(HttpMethod.POST, "/catalogue/products/:productType/:productID/")
.handler(ctx -> {String productType = ctx.pathParam("productType");
String productID = ctx.pathParam("productID");
HttpServerResponse response = ctx.response();
response.putHeader("content-type", "text/plain");
response.end(productType + "--" + productID);
});
$ curl -X POST http://127.0.0.1:8080/catalogue/products/String/123/
String--123
如果对编程感兴趣,请关注我的集体博客 https://www.lzmvlog.top/
本文由博客一文多发平台 OpenWrite 公布!