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 發布!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/259919.html
標籤:其他
上一篇:Java入門及環境搭建
