关于java:Vertx初体验

39次阅读

共计 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 返回异步响应,路由器包含处理程序的快捷方式,以确保:

  1. 响应以 JSON 返回。
  2. 如果解决处理程序时产生谬误,则返回正确的谬误。
  3. 如果序列化对 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/");
});

间接调用

getpostputdelete 等以 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 公布!

正文完
 0