前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vert .x初体验

Vert .x初体验

原创
作者头像
是小张啊喂
修改2021-02-08 10:01:57
9950
修改2021-02-08 10:01:57
举报
文章被收录于专栏:软件软件

Vert .x

什么是Vert .x

Vert.x框架基于事件和异步,依托于全异步Java服务器Netty,并扩展了很多其他特性,以其轻量、高性能、支持多语言开发

Hello world

创建一个简单的项目https://start.vertx.io/ 无需添加任何依赖

代码语言:javascript
复制
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

下面两个命令很重要切记

代码语言:javascript
复制
打包
$ 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依赖

代码语言:javascript
复制
<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-web</artifactId>
</dependency>
代码语言:javascript
复制
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()
        )
      );
  }
 }
代码语言:javascript
复制
访问
$ 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请求,并找到该请求的第一个匹配路由,然后将请求传递到该路由。

路由可以具有与之关联的处理程序,该处理程序然后接收请求。然后您可以对请求进行处理,然后结束请求或将其传递给下一个匹配的处理程序。

创建一个简单的路由:

代码语言:javascript
复制
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以便其他匹配的路由可以处理请求(如果有)。

代码语言:javascript
复制
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();
});
代码语言:javascript
复制
$ 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的响应时出错,则返回正确的错误。
代码语言:javascript
复制
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()));
代码语言:javascript
复制
$ curl http://127.0.0.1:8080/some/path/
{"hello":"world"}

但是,如果提供的函数调用write或,您也可以将其用于非JSON响应end

代码语言:javascript
复制
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..."));
代码语言:javascript
复制
$ curl http://127.0.0.1:8080/some/path/
hello world!

$ curl http://127.0.0.1:8080/some/path/
Write some text...

路由

按确切路径路由
代码语言:javascript
复制
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");
});
通过以某些内容开头的路径进行路由
代码语言:javascript
复制
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方法路由
代码语言:javascript
复制
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方法名称命名

代码语言:javascript
复制
router
  .get("/some/path")
  .respond(
    ctx -> ctx
      .response()
        .putHeader("Content-Type", "text/plain")
        .end("hello world!"));

如果要指定一个路由将匹配多个HTTP方法,则可以method 多次调用:

代码语言:javascript
复制
Route route = router.route().method(HttpMethod.POST).method(HttpMethod.PUT);
route.handler(ctx -> {});

如果要创建需要自定义HTTP动词的应用程序(例如WebDav服务器),则可以指定自定义动词

代码语言:javascript
复制
Route route = router.route()
  .method(HttpMethod.valueOf("MKCOL"))
  .handler(ctx -> {
    // 任何MKCOL请求都将调用此处理程序
  });
路线顺序

参考 处理请求并调用下一个处理程序

如果要覆盖路由的默认顺序,可以使用order,指定一个整数值。

路由在创建时被分配一个与添加到路由器的顺序相对应的顺序,第一个路由编号0,第二个路由编号1,依此类推。

通过指定路线的顺序,您可以覆盖默认顺序。订单也可以是负数,例如,如果您要确保在路线编号之前评估一条路线0

代码语言:javascript
复制
 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();
      });
代码语言:javascript
复制
$ curl http://127.0.0.1:8080/some/path/
route2
route1
route3

关于路由得东西太多,后面单独整理一期,单独研究一下,刚开始学习的话,还是先会用比较好

捕获路径参数

代码语言:javascript
复制
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);
    });
代码语言:javascript
复制
$ curl -X POST http://127.0.0.1:8080/catalogue/products/String/123/
String--123

学习这件事,不是缺乏时间,而是缺乏努力。

如果对编程感兴趣,请关注我的个人博客 https://www.lzmvlog.top/

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Vert .x
    • 什么是Vert .x?
      • Hello world
        • Run
          • web项目
            • 按确切路径路由
            • 通过以某些内容开头的路径进行路由
            • 通过HTTP方法路由
            • 直接调用
            • 路线顺序
        • Vert.x-Web基本概念
        • 处理请求并调用下一个处理程序
        • 简单的回应
        • 路由
        • 捕获路径参数
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档