Vert.x Web之Router

  Vert.x Web 是一系列用於基於 Vert.x 構建 Web 應用的構建模塊。html

  Vert.x Web 的大多數特性被實現爲了處理器(Handler),所以您隨時能夠實現您本身的處理器。咱們預計隨着時間的推移會有更多的處理器被實現。web

使用 Vert.x Web

  

<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-web</artifactId>
  <version>3.4.2</version>
</dependency>

回顧 Vert.x Core 的 HTTP 服務端

HttpServer server = vertx.createHttpServer();

server.requestHandler(request -> {

  // 全部的請求都會調用這個處理器處理
  HttpServerResponse response = request.response();
  response.putHeader("content-type", "text/plain");

  // 寫入響應並結束處理
  response.end("Hello World!");
});

server.listen(8080);

Vert.x Web 的基本概念

  Router 是 Vert.x Web 的核心概念之一。它是一個維護了零或多個 Route 的對象。json

  Router 接收 HTTP 請求,並查找首個匹配該請求的 Route,而後將請求傳遞給這個 Routeapi

  Route 能夠持有一個與之關聯的處理器用於接收請求。您能夠經過這個處理器對請求作一些事情,而後結束響應或者把請求傳遞給下一個匹配的處理器。服務器

  如下是一個簡單的路由示例:app

HttpServer server = vertx.createHttpServer();

Router router = Router.router(vertx);

router.route().handler(routingContext -> {

  // 全部的請求都會調用這個處理器處理
  HttpServerResponse response = routingContext.response();
  response.putHeader("content-type", "text/plain");

  // 寫入響應並結束處理
  response.end("Hello World from Vert.x-Web!");
});

server.requestHandler(router::accept).listen(8080);

  作了和上文使用 Vert.x Core 實現的 HTTP 服務器基本相同的事情,只是這一次換成了 Vert.x Web。post

  和上文同樣,咱們建立了一個 HTTP 服務器,而後建立了一個 Router。在這以後,咱們建立了一個沒有匹配條件的 Route,這個 route 會匹配全部到達這個服務器的請求。spa

  以後,咱們爲這個 route 指定了一個處理器,全部的請求都會調用這個處理器處理。線程

  調用處理器的參數是一個 RoutingContext 對象。它不只包含了 Vert.x 中標準的 HttpServerRequest 和HttpServerResponse,還包含了各類用於簡化 Vert.x Web 使用的東西。code

  每個被路由的請求對應一個惟一的 RoutingContext,這個實例會被傳遞到全部處理這個請求的處理器上。

處理請求並調用下一個處理器

  當 Vert.x Web 決定路由一個請求到匹配的 route 上,它會使用一個 RoutingContext 調用對應處理器。

  若是您不在處理器裏結束這個響應,您須要調用 next 方法讓其餘匹配的 Route 來處理請求(若是有)。

  您不須要在處理器執行完畢時調用 next 方法。您能夠在以後您須要的時間點調用它:

Route route1 = router.route("/some/path/").handler(routingContext -> {

  HttpServerResponse response = routingContext.response();
  // 因爲咱們會在不一樣的處理器裏寫入響應,所以須要啓用分塊傳輸
  // 僅當須要經過多個處理器輸出響應時才須要
  response.setChunked(true);

  response.write("route1\n");

  // 5 秒後調用下一個處理器
  routingContext.vertx().setTimer(5000, tid -> routingContext.next());
});

Route route2 = router.route("/some/path/").handler(routingContext -> {

  HttpServerResponse response = routingContext.response();
  response.write("route2\n");

  // 5 秒後調用下一個處理器
  routingContext.vertx().setTimer(5000, tid ->  routingContext.next());
});

Route route3 = router.route("/some/path/").handler(routingContext -> {

  HttpServerResponse response = routingContext.response();
  response.write("route3");

  // 結束響應
  routingContext.response().end();
});

  在上述的例子中,route1 向響應裏寫入了數據,5秒以後 route2 向響應裏寫入了數據,再5秒以後 route3 向響應裏寫入了數據並結束了響應。

  注意,全部發生的這些沒有線程阻塞。

下面看一個route自寫的例子

public class FirstMain extends AbstractVerticle {

    private static Logger logger = LoggerFactory.getLogger(FirstMain.class);

    public void start() {

        HttpServer server = vertx.createHttpServer();

        Router router = Router.router(vertx);
        router.get("/hang/some").handler(routingContext -> { //指定get方法

            // 全部的請求都會調用這個處理器處理
            HttpServerResponse response = routingContext.response();
            response.putHeader("content-type", "text/plain");

            // 寫入響應並結束處理
            response.end("Hello World from Vert.x-Web!");
        });
        router.route("/hang/all").handler(routingContext -> {

            // 全部的請求都會調用這個處理器處理
            HttpServerResponse response = routingContext.response();
            response.putHeader("content-type", "text/plain");

            // 寫入響應並結束處理
            response.end("Hello World !");
        });
        router.route("/hang/put").handler(BodyHandler::getStr);
//        router.route("/static/*").handler(StaticHandler.create());
        //處理請求並調用下一個處理器
        router.route(HttpMethod.POST,"/hang/add").handler(BodyHandler::getStr_1);//OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT, PATCH, OTHER
        router.route("/hang/add").handler(BodyHandler::getStr_2);
        router.route("/hang/add").handler(BodyHandler::getStr_3);

        router.route("/hello").blockingHandler(BodyHandler.bodyHandler()::getStr_4, false);

        server.requestHandler(router::accept).listen(8080);
    }


    public static void main(String[] args) {
//        Vertx vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(40));
//        vertx.deployVerticle(FirstMain.class.getName());
//        System.out.println("vertx......啓動");
        Vertx.clusteredVertx(new VertxOptions(), res->{
            if (res.succeeded()) {
                res.result().deployVerticle(FirstMain.class.getName());
                logger.info("success start!" );
                System.out.println("success start!" );
            } else {
                logger.info("Failed: " + res.cause());
            }
        });

    }
}

BodyHandler類:

public class BodyHandler {
    //    private Vertx vertx;
    private static BodyHandler bodyHandler = new BodyHandler();
    public Logger logger = LoggerFactory.getLogger(BodyHandler.class);

    public static BodyHandler bodyHandler() {
        return bodyHandler;
    }

    public static void getStr(RoutingContext rc){
        rc.response().end("Hello world! 我!");
    }

    public static void getStr_1(RoutingContext rc){
        HttpServerResponse response = rc.response();
        // 因爲咱們會在不一樣的處理器裏寫入響應,所以須要啓用分塊傳輸,僅當須要經過多個處理器輸出響應時才須要
        response.setChunked(true);
        response.write("我");
        rc.next();
        // 5 秒後調用下一個處理器
//        rc.vertx().setTimer(5000, tid ->  rc.next());
    }

    public static void getStr_2(RoutingContext rc){
        HttpServerResponse response = rc.response();
        response.write("和");
        rc.next();
    }

    public static void getStr_3(RoutingContext rc){
        HttpServerResponse response = rc.response();
        response.write("你");
        rc.response().end();
    }

    public void getStr_4(RoutingContext rc){
        ObjectMapper om = new ObjectMapper();
        if ("1".equals("1")) {
            getOrder("1", res -> {
                if (res.succeeded()) {
                    try {
                        rc.response().putHeader("Content-type", "application/json; charset=UTF-8");
                        rc.response().end(om.writeValueAsString(res.result()));
                        System.out.println("我是第四個打印!");
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
                }else{
                    rc.response().setStatusCode(500)
                            .putHeader("Content-type", "application/json; charset=UTF-8")
                            .end((Buffer) new JsonObject().put("status", 0).put("des", "fali"));
                }
            });
            System.out.println("我是第一個打印!");
        }
    }


    private void getOrder(String orderId, Handler<AsyncResult<String>> handler){
        Vertx vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(40));
        vertx.<String>executeBlocking(future -> {
            try {
                Thread.sleep(1);
                System.out.println("我是第二個打印!");
                future.complete("成功!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },false, res->{
            if (res.succeeded()) {
                System.out.println("我是第三個打印!");
                handler.handle(Future.succeededFuture(res.result()));
            } else {
                handler.handle(Future.failedFuture(res.cause()));
            }
        });
    }
}

訪問 http://localhost:8080//hang/some   獲得:Hello World from Vert.x-Web!

訪問 http://localhost:8080//hang/all   獲得:Hello World !

訪問 http://localhost:8080//hang/put   獲得:Hello world! 我!

訪問 http://localhost:8080/hang/add   獲得:我和你  (post方式)

訪問 http://localhost:8080/helo   獲得:"成功!"

並輸出以下:

我是第一個打印!我是第二個打印!我是第三個打印!我是第四個打印!

相關文章
相關標籤/搜索