Vert .x
?Vert.x框架基於事件和異步,依託於全異步Java服務器Netty,並擴展了不少其餘特性,以其輕量、高性能、支持多語言開發html
Hello world
建立一個簡單的項目https://start.vertx.io/ 無需添加任何依賴java
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()); } }); }
這個代碼第一眼看上去就很複雜,可是其實仔細分析一下,會感受其實很好理解web
大體就是Vert.x
建立了一個Http
的服務,並添加請求頭和響應的內容,監聽8888
的端口,當服務建立成功時輸出HTTP server started on port 8888
shell
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
依賴json
<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"}
Router
是Vert.x-Web的核心概念之一。它是保持零個或多個的對象 Routes
。服務器
路由器接收一個HTTP請求,並找到該請求的第一個匹配路由,而後將請求傳遞到該路由。app
路由能夠具備與之關聯的處理程序,該處理程序而後接收請求。而後,您能夠對請求進行處理,而後結束請求或將其傳遞給下一個匹配的處理程序。框架
建立一個簡單的路由:curl
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返回異步響應,路由器包括處理程序的快捷方式,以確保:
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/*"); });
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 發佈!